Skip to content

Commit

Permalink
Merge pull request google-ai-edge#1 from googlesamples/android_object…
Browse files Browse the repository at this point in the history
…_detection

Adding initial Object Detection sample for MediaPipe Android
  • Loading branch information
PaulTR authored Nov 18, 2022
2 parents 9c776b2 + a45b0bf commit a03708a
Show file tree
Hide file tree
Showing 50 changed files with 2,829 additions and 2 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2022 The MediaPipe Authors. All rights reserved.
Copyright 2022 The TensorFlow Authors. All rights reserved.

Apache License
Version 2.0, January 2004
Expand Down
46 changes: 45 additions & 1 deletion examples/object_detection/android/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,45 @@
placeholder README.md
# MediaPipe Tasks Object Detection Android Demo

### Overview

This is a camera app that continuously detects the objects (bounding boxes and
classes) in the frames seen by your device's back camera, in an image imported from the device gallery,
or in a video imported by the device gallery, with the option to use a quantized
[MobileNetV2](https://storage.cloud.google.com/tf_model_garden/vision/qat/mobilenetv2_ssd_coco/mobilenetv2_ssd_256_uint8.tflite)
[EfficientDet Lite 0](https://storage.googleapis.com/mediapipe-tasks/object_detector/efficientdet_lite0_uint8.tflite),
or [EfficientDet Lite2](https://storage.googleapis.com/mediapipe-tasks/object_detector/efficientdet_lite2_uint8.tflite)

The model files are downloaded via Gradle scripts when you build and run the
app. You don't need to do any steps to download TFLite models into the project
explicitly.

This application should be run on a physical Android device.

## Build the demo using Android Studio

### Prerequisites

* The **[Android Studio](https://developer.android.com/studio/index.html)**
IDE. This sample has been tested on Android Studio Dolphin.

* A physical Android device with a minimum OS version of SDK 24 (Android 7.0 -
Nougat) with developer mode enabled. The process of enabling developer mode
may vary by device.

### Building

* Open Android Studio. From the Welcome screen, select Open an existing
Android Studio project.

* From the Open File or Project window that appears, navigate to and select
the mediapipe/examples/object_detection/android directory. Click OK.

* If it asks you to do a Gradle Sync, click OK.

* With your Android device connected to your computer and developer mode
enabled, click on the green Run arrow in Android Studio.

### Models used

Downloading, extraction, and placing the models into the assets folder is
managed automatically by the download.gradle file.
119 changes: 119 additions & 0 deletions examples/object_detection/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: "androidx.navigation.safeargs"
apply plugin: 'de.undercouch.download'

android {
compileSdkVersion 32
defaultConfig {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
applicationId "com.google.mediapipe.examples.objectdetection"
minSdkVersion 24
targetSdkVersion 32
versionCode 1
versionName "1.0.0"
}

dataBinding {
enabled = true
}

compileOptions {
sourceCompatibility rootProject.ext.java_version
targetCompatibility rootProject.ext.java_version
}

kotlinOptions {
jvmTarget = rootProject.ext.java_version
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

buildFeatures {
viewBinding true
}
androidResources {
noCompress 'tflite'
}

}

// import DownloadModels task
project.ext.ASSET_DIR = projectDir.toString() + '/src/main/assets'

// Download default models; if you wish to use your own models then
// place them in the "assets" directory and comment out this line.
apply from:'download_models.gradle'

dependencies {
// Kotlin lang
implementation 'androidx.core:core-ktx:1.6.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'

// App compat and UI things
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'

// Navigation library
def nav_version = "2.3.5"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

// CameraX core library
def camerax_version = '1.1.0'
implementation "androidx.camera:camera-core:$camerax_version"

// CameraX Camera2 extensions
implementation "androidx.camera:camera-camera2:$camerax_version"

// CameraX Lifecycle library
implementation "androidx.camera:camera-lifecycle:$camerax_version"

// CameraX View class
implementation "androidx.camera:camera-view:$camerax_version"

//WindowManager
implementation 'androidx.window:window:1.0.0-alpha09'

// Unit testing
testImplementation 'androidx.test.ext:junit:1.1.3'
testImplementation 'androidx.test:rules:1.4.0'
testImplementation 'androidx.test:runner:1.4.0'
testImplementation 'androidx.test.espresso:espresso-core:3.4.0'
testImplementation 'org.robolectric:robolectric:4.4'

// Instrumented testing
androidTestImplementation "androidx.test.ext:junit:1.1.3"
androidTestImplementation "androidx.test:core:1.4.0"
androidTestImplementation "androidx.test:rules:1.4.0"
androidTestImplementation "androidx.test:runner:1.4.0"
androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0"

implementation 'com.google.mediapipe:tasks-vision:0.1.0-alpha-2'
}
19 changes: 19 additions & 0 deletions examples/object_detection/android/app/download_models.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
task downloadModelFile0(type: Download) {
src 'https://storage.googleapis.com/mediapipe-tasks/object_detector/efficientdet_lite0_uint8.tflite'
dest project.ext.ASSET_DIR + '/efficientdet-lite0.tflite'
overwrite false
}

task downloadModelFile1(type: Download) {
src 'https://storage.googleapis.com/mediapipe-tasks/object_detector/efficientdet_lite2_uint8.tflite'
dest project.ext.ASSET_DIR + '/efficientdet-lite2.tflite'
overwrite false
}

task downloadModelFile2(type: Download) {
src 'https://storage.cloud.google.com/tf_model_garden/vision/qat/mobilenetv2_ssd_coco/mobilenetv2_ssd_256_uint8.tflite'
dest project.ext.ASSET_DIR + '/mobilenetv2.tflite'
overwrite false
}

preBuild.dependsOn downloadModelFile0, downloadModelFile1
21 changes: 21 additions & 0 deletions examples/object_detection/android/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.mediapipe.examples.objectdetection

import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith

/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ObjectDetectorTest {

// TODO: Add tests to validate image, video, and streaming results
@Test
@Throws(Exception::class)
fun detectionResultsShouldNotChange() {
assertTrue(true)
}
}
64 changes: 64 additions & 0 deletions examples/object_detection/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2022 The TensorFlow Authors. All Rights Reserved.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dist="http://schemas.android.com/apk/distribution"
xmlns:tools="http://schemas.android.com/tools"
package="com.google.mediapipe.examples.objectdetection">

<!-- Enable instant app support -->
<dist:module dist:instant="true" />

<!-- Declare features -->
<uses-feature android:name="android.hardware.camera" />

<!-- Declare permissions -->
<uses-permission android:name="android.permission.CAMERA" />

<application
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
android:allowBackup="true"
android:taskAffinity=""
tools:ignore="AllowBackup">

<activity
android:name=".MainActivity"
android:clearTaskOnLaunch="true"
android:theme="@style/AppTheme"
android:exported="true"
android:icon="@mipmap/ic_launcher"
android:rotationAnimation="seamless"
android:resizeableActivity="true"
android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize"
tools:targetApi="O">

<!-- Main app intent filter -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<!-- Declare notch support -->
<meta-data android:name="android.notch_support" android:value="true"/>

</activity>

</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.mediapipe.examples.objectdetection

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.google.mediapipe.examples.objectdetection.databinding.ActivityMainBinding

/**
* Main entry point into our app. This app follows the single-activity pattern, and all
* functionality is implemented in the form of fragments.
*/
class MainActivity : AppCompatActivity() {

private lateinit var activityMainBinding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)

val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
val navController = navHostFragment.navController
activityMainBinding.navigation.setupWithNavController(navController)
activityMainBinding.navigation.setOnNavigationItemReselectedListener {
// ignore the reselection
}
}

override fun onBackPressed() {
finish()
}
}
Loading

0 comments on commit a03708a

Please sign in to comment.