├── README.md ├── TFlitedemo ├── .gitignore ├── .idea │ ├── gradle.xml │ ├── misc.xml │ ├── modules.xml │ └── runConfigurations.xml ├── README.md ├── app │ ├── build.gradle │ ├── libs │ │ └── libtensorflowlite.jar │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ ├── labels.txt │ │ ├── labels_imagenet_slim.txt │ │ ├── labels_mobilenet_quant_v1_224.txt │ │ └── mobilenet_quant_v1_224.tflite │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── android │ │ │ └── tflitecamerademo │ │ │ ├── AutoFitTextureView.java │ │ │ ├── Camera2BasicFragment.java │ │ │ ├── CameraActivity.java │ │ │ ├── ImageClassifier.java │ │ │ ├── ImageClassifierFloatInception.java │ │ │ └── ImageClassifierQuantizedMobileNet.java │ │ ├── jnilibs │ │ └── arm64-v8a │ │ │ └── libtensorflowlite_jni.so │ │ └── res │ │ ├── drawable-hdpi │ │ ├── ic_action_info.png │ │ ├── ic_launcher.png │ │ └── tile.9.png │ │ ├── drawable-mdpi │ │ ├── ic_action_info.png │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ ├── ic_action_info.png │ │ └── ic_launcher.png │ │ ├── drawable-xxhdpi │ │ ├── ic_action_info.png │ │ ├── ic_launcher.png │ │ └── logo.png │ │ ├── layout-land │ │ └── fragment_camera2_basic.xml │ │ ├── layout-v26 │ │ └── fragment_camera2_basic.xml │ │ ├── layout │ │ ├── activity_camera.xml │ │ └── fragment_camera2_basic.xml │ │ ├── values-sw600dp │ │ ├── template-dimens.xml │ │ └── template-styles.xml │ │ ├── values-v11 │ │ └── template-styles.xml │ │ ├── values-v21 │ │ ├── base-colors.xml │ │ └── base-template-styles.xml │ │ └── values │ │ ├── base-strings.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ ├── template-dimens.xml │ │ └── template-styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle └── TfLiteCameraDemo ├── .idea ├── gradle.xml ├── libraries │ ├── junit_junit_4_12_jar.xml │ └── org_hamcrest_hamcrest_core_1_3_jar.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── workspace.xml ├── TfLiteCameraDemo.iml ├── android.iml ├── app ├── app.iml ├── build.gradle ├── download-models.gradle ├── libs │ └── libtensorflowlite.jar └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── box_priors.txt │ ├── coco_labels_list.txt │ ├── conv_actions_labels.txt │ ├── download.sh │ ├── labels.txt │ ├── labels_list.txt │ └── labels_mobilenet_quant_v1_224.txt │ ├── java │ └── org │ │ └── tensorflow │ │ └── demo │ │ ├── AutoFitTextureView.java │ │ ├── CameraActivity.java │ │ ├── CameraConnectionFragment.java │ │ ├── Classifier.java │ │ ├── ClassifierActivity.java │ │ ├── DetectorActivity.java │ │ ├── LegacyCameraConnectionFragment.java │ │ ├── OverlayView.java │ │ ├── RecognitionScoreView.java │ │ ├── RecognizeCommands.java │ │ ├── ResultsView.java │ │ ├── SpeechActivity.java │ │ ├── TFLiteImageClassifier.java │ │ ├── TFLiteObjectDetectionAPIModel.java │ │ ├── env │ │ ├── AssetUtils.java │ │ ├── BorderedText.java │ │ ├── ImageUtils.java │ │ ├── Logger.java │ │ ├── Size.java │ │ └── SplitTimer.java │ │ └── tracking │ │ ├── MultiBoxTracker.java │ │ └── ObjectTracker.java │ ├── jnilibs │ └── arm64-v8a │ │ ├── libtensorflow_demo.so │ │ └── libtensorflowlite_jni.so │ └── res │ ├── animator │ └── color_animation.xml │ ├── drawable-hdpi │ ├── ic_action_info.png │ ├── ic_launcher.png │ └── tile.9.png │ ├── drawable-mdpi │ ├── ic_action_info.png │ └── ic_launcher.png │ ├── drawable-xhdpi │ ├── ic_action_info.png │ └── ic_launcher.png │ ├── drawable-xxhdpi │ ├── ic_action_info.png │ └── ic_launcher.png │ ├── drawable │ └── border.xml │ ├── layout │ ├── activity_camera.xml │ ├── activity_speech.xml │ ├── camera_connection_fragment.xml │ ├── camera_connection_fragment_stylize.xml │ ├── camera_connection_fragment_tracking.xml │ └── list_text_item.xml │ ├── values-sw600dp │ ├── template-dimens.xml │ └── template-styles.xml │ ├── values-v11 │ ├── styles.xml │ └── template-styles.xml │ ├── values-v14 │ └── styles.xml │ ├── values-v21 │ ├── base-colors.xml │ └── base-template-styles.xml │ └── values │ ├── attrs.xml │ ├── base-strings.xml │ ├── colors.xml │ ├── strings.xml │ ├── styles.xml │ ├── template-dimens.xml │ └── template-styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties └── settings.gradle /README.md: -------------------------------------------------------------------------------- 1 | # Tensorflow_Lite_Demo 2 | An example Android application using TensorFLow Lite is available on Tensorflow github, Creating a project directory in tensorflow/tensorflow/contrib/lite/ , which is builted on Android studio 3.0.I have download the model of tflite format and complie the libtensorflowlite_jni.so and libtensorflowlite.jar 3 | 4 | 5 | In the demo app, inference is done using the TensorFlow Lite Java API. The demo app classifies frames in real-time, displaying the top most probable classifications. It also displays the inference time taken to detect the object. 6 | 7 | # There are two ways to get the demo app to your device: 8 | 1,Use Android Studio to build the application. Here it's mine work ! 9 | 2,Download the source code for TensorFlow Lite and the demo and build it using bazel.I have just give building commands ! 10 | 11 | 12 | To build the demo app, run bazel: 13 | # TfLiteCameraDemo ---- The demo app classifier 14 | #./tensorflow direction run the bellow command 15 | 16 | bazel build --cxxopt=--std=c++11 //tensorflow/contrib/lite/java/demo/app/src/main:TfLiteCameraDemo 17 | 18 | for more infomation about [TfLiteCameraDemo](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/lite/java/demo) 19 | 20 | # tflite_demo ---- The demo app on classifier, detector, speech 21 | #./tensorflow direction run the bellow command 22 | 23 | sudo bazel build -c opt --config=android_arm{,64} --cxxopt='--std=c++11' "//tensorflow/contrib/lite/examples/android:tflite_demo" 24 | 25 | for more infomation about [tflite_demo](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/lite/examples/android/app) 26 | 27 | # bazel-bin/tensorflow/contrib/lite/java/libtensorflowlite.jar ---- the java api for tensorflow lite 28 | 29 | sudo bazel build -c opt --config=android_arm{,64} --cxxopt='--std=c++11' "//tensorflow/contrib/lite/java:tensorflowlite" 30 | 31 | # bazel-bin/tensorflow/examples/android/libtensorflow_demo.so ---- the native c++ jni interface for libtensorflowlite.jar 32 | 33 | sudo bazel build -c opt --config=android_arm{,64} --cxxopt='--std=c++11' "//tensorflow/examples/android:libtensorflow_demo.so" 34 | 35 | 36 | # attention 37 | 1, Edit your WORKSPACE to add SDK and NDK targets. 38 | 39 | android_sdk_repository( 40 | name = "androidsdk", 41 | api_level = 25, 42 | # Ensure that you have the build_tools_version below installed in the 43 | # SDK manager as it updates periodically. 44 | build_tools_version = "26.0.1", 45 | # Replace with path to Android SDK on your system 46 | path = "/home/XXXX/Software/SDK", 47 | ) 48 | 49 | android_ndk_repository( 50 | name="androidndk", 51 | path="/home/XXXX/Software/NDK/android-ndk-r13b", 52 | # This needs to be 14 or higher to compile TensorFlow. 53 | # Please specify API level to >= 21 to build for 64-bit 54 | # archtectures or the Android NDK will automatically select biggest 55 | # API level that it supports without notice. 56 | # Note that the NDK version is not the API level. 57 | api_level=25) 58 | 59 | 60 | 2, Build this demo app with Bazel. The demo needs C++11. We configure the fat_apk_cpu flag to package support for 4 hardware variants. You may replace it with --config=android_arm64 on a 64-bit device and --config=android_arm for 32-bit device: 61 | For examples: 62 | 63 | bazel build -c opt --cxxopt='--std=c++11' --fat_apk_cpu=x86,x86_64,arm64-v8a,armeabi-v7a \ 64 | //tensorflow/contrib/lite/examples/android:tflite_demo 65 | 66 | 67 | bazel build -c opt --config=android_arm{,64} --cxxopt='--std=c++11' "//tensorflow/contrib/lite/examples/android:tflite_demo" 68 | 69 | 3, Build the Tensorflow mobile demo using Bazel,which has a fuller set of supported functionality, while TensorFlow Lite supports only a limited set of operators, so not all models will work on it by default. 70 | 71 | #bazel-bin/tensorflow/examples/android/tensorflow_demo.apk 72 | bazel build -c opt //tensorflow/examples/android:tensorflow_demo 73 | 74 | #bazel-bin/tensorflow/contrib/android/libandroid_tensorflow_inference_java.jar 75 | bazel build //tensorflow/contrib/android:android_tensorflow_inference_java 76 | 77 | #bazel-bin/tensorflow/contrib/android/libtensorflow_inference.so 78 | sudo bazel build -c opt //tensorflow/contrib/android:libtensorflow_inference.so --crosstool_top=//external:android/crosstool --host_crosstool_top=@bazel_tools//tools/cpp:toolchain --cpu=armeabi-v7a --cxxopt='--std=c++11' --verbose_failures 79 | for more information about [Tensorflow Mobile] (https://www.tensorflow.org/mobile/android_build) 80 | 81 | 82 | -------------------------------------------------------------------------------- /TFlitedemo/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /TFlitedemo/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /TFlitedemo/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /TFlitedemo/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TFlitedemo/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /TFlitedemo/README.md: -------------------------------------------------------------------------------- 1 | # TF Lite Android App 2 | 3 | ## Building in Android Studio with TensorFlow Lite AAR from JCenter. 4 | The build.gradle is configured to use TensorFlow Lite's nightly build. 5 | 6 | If you see a build error related to compatibility with Tensorflow Lite's Java API (example: method X is 7 | undefined for type Interpreter), there has likely been a backwards compatible 8 | change to the API. You will need to pull new app code that's compatible with the 9 | nightly build and may need to first wait a few days for our external and internal 10 | code to merge. 11 | 12 | ## Building from Source with Bazel 13 | 14 | 1. Follow the [Bazel steps for the TF Demo App](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android#bazel): 15 | 16 | 1. [Install Bazel and Android Prerequisites](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android#install-bazel-and-android-prerequisites). 17 | It's easiest with Android Studio. 18 | 19 | - You'll need at least SDK version 23. 20 | - Make sure to install the latest version of Bazel. Some distributions 21 | ship with Bazel 0.5.4, which is too old. 22 | - Bazel requires Android Build Tools `26.0.1` or higher. 23 | - **Bazel is incompatible with NDK revisions 15 and above,** with revision 24 | 16 being a compile-breaking change. [Download an older version manually 25 | instead of using the SDK Manager.](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android#install-bazel-and-android-prerequisites) 26 | - You also need to install the Android Support Repository, available 27 | through Android Studio under `Android SDK Manager -> SDK Tools -> 28 | Android Support Repository`. 29 | 30 | 2. [Edit your `WORKSPACE`](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android#edit-workspace) 31 | to add SDK and NDK targets. 32 | 33 | NOTE: As long as you have the SDK and NDK installed, the `./configure` 34 | script will create these rules for you. Answer "Yes" when the script asks 35 | to automatically configure the `./WORKSPACE`. 36 | 37 | - Make sure the `api_level` in `WORKSPACE` is set to an SDK version that 38 | you have installed. 39 | - By default, Android Studio will install the SDK to `~/Android/Sdk` and 40 | the NDK to `~/Android/Sdk/ndk-bundle` (but the NDK should be a manual 41 | download until Bazel supports NDK 16. See bullet points under (1)). 42 | 43 | 2. Build the app with Bazel. The demo needs C++11: 44 | 45 | ```shell 46 | bazel build -c opt --cxxopt='--std=c++11' \ 47 | //tensorflow/contrib/lite/java/demo/app/src/main:TfLiteCameraDemo 48 | ``` 49 | 50 | 3. Install the demo on a 51 | [debug-enabled device](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android#install): 52 | 53 | ```shell 54 | adb install bazel-bin/tensorflow/contrib/lite/java/demo/app/src/main/TfLiteCameraDemo.apk 55 | ``` 56 | -------------------------------------------------------------------------------- /TFlitedemo/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | buildToolsVersion '26.0.2' 6 | defaultConfig { 7 | applicationId "android.example.com.tflitecamerademo" 8 | // Required by Camera2 API. 9 | minSdkVersion 21 10 | targetSdkVersion 26 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | 15 | 16 | } 17 | lintOptions { 18 | abortOnError false 19 | } 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | aaptOptions { 27 | noCompress "tflite" 28 | } 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | 35 | sourceSets { 36 | main { 37 | // let gradle pack the shared library into apk 38 | jniLibs.srcDirs = ['src/main/jnilibs'] 39 | } 40 | } 41 | } 42 | 43 | repositories { 44 | maven { 45 | url 'https://google.bintray.com/tensorflow' 46 | } 47 | } 48 | 49 | dependencies { 50 | compile fileTree(dir: 'libs', include: ['*.jar']) 51 | 52 | compile 'com.android.support:appcompat-v7:25.2.0' 53 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 54 | compile 'com.android.support:design:25.2.0' 55 | compile 'com.android.support:support-annotations:25.3.1' 56 | compile 'com.android.support:support-v13:25.2.0' 57 | 58 | //compile 'org.tensorflow:tensorflow-lite:0.0.0-nightly' 59 | 60 | testCompile 'junit:junit:4.12' 61 | } -------------------------------------------------------------------------------- /TFlitedemo/app/libs/libtensorflowlite.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/libs/libtensorflowlite.jar -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 32 | 33 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/assets/mobilenet_quant_v1_224.tflite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/src/main/assets/mobilenet_quant_v1_224.tflite -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/java/com/example/android/tflitecamerademo/AutoFitTextureView.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2017 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package com.example.android.tflitecamerademo; 17 | 18 | import android.content.Context; 19 | import android.util.AttributeSet; 20 | import android.view.TextureView; 21 | 22 | /** A {@link TextureView} that can be adjusted to a specified aspect ratio. */ 23 | public class AutoFitTextureView extends TextureView { 24 | 25 | private int mRatioWidth = 0; 26 | private int mRatioHeight = 0; 27 | 28 | public AutoFitTextureView(Context context) { 29 | this(context, null); 30 | } 31 | 32 | public AutoFitTextureView(Context context, AttributeSet attrs) { 33 | this(context, attrs, 0); 34 | } 35 | 36 | public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) { 37 | super(context, attrs, defStyle); 38 | } 39 | 40 | /** 41 | * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio 42 | * calculated from the parameters. Note that the actual sizes of parameters don't matter, that is, 43 | * calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result. 44 | * 45 | * @param width Relative horizontal size 46 | * @param height Relative vertical size 47 | */ 48 | public void setAspectRatio(int width, int height) { 49 | if (width < 0 || height < 0) { 50 | throw new IllegalArgumentException("Size cannot be negative."); 51 | } 52 | mRatioWidth = width; 53 | mRatioHeight = height; 54 | requestLayout(); 55 | } 56 | 57 | @Override 58 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 59 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 60 | int width = MeasureSpec.getSize(widthMeasureSpec); 61 | int height = MeasureSpec.getSize(heightMeasureSpec); 62 | if (0 == mRatioWidth || 0 == mRatioHeight) { 63 | setMeasuredDimension(width, height); 64 | } else { 65 | if (width < height * mRatioWidth / mRatioHeight) { 66 | setMeasuredDimension(width, width * mRatioHeight / mRatioWidth); 67 | } else { 68 | setMeasuredDimension(height * mRatioWidth / mRatioHeight, height); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/java/com/example/android/tflitecamerademo/CameraActivity.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2017 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package com.example.android.tflitecamerademo; 17 | 18 | import android.app.Activity; 19 | import android.os.Bundle; 20 | 21 | /** Main {@code Activity} class for the Camera app. */ 22 | public class CameraActivity extends Activity { 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_camera); 28 | if (null == savedInstanceState) { 29 | getFragmentManager() 30 | .beginTransaction() 31 | .replace(R.id.container, Camera2BasicFragment.newInstance()) 32 | .commit(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/java/com/example/android/tflitecamerademo/ImageClassifierFloatInception.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2017 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package com.example.android.tflitecamerademo; 17 | 18 | import android.app.Activity; 19 | 20 | import java.io.IOException; 21 | 22 | /** 23 | * This classifier works with the Inception-v3 slim model. 24 | * It applies floating point inference rather than using a quantized model. 25 | */ 26 | public class ImageClassifierFloatInception extends ImageClassifier { 27 | 28 | /** 29 | * The inception net requires additional normalization of the used input. 30 | */ 31 | private static final int IMAGE_MEAN = 128; 32 | private static final float IMAGE_STD = 128.0f; 33 | 34 | /** 35 | * An array to hold inference results, to be feed into Tensorflow Lite as outputs. 36 | * This isn't part of the super class, because we need a primitive array here. 37 | */ 38 | private float[][] labelProbArray = null; 39 | 40 | /** 41 | * Initializes an {@code ImageClassifier}. 42 | * 43 | * @param activity 44 | */ 45 | ImageClassifierFloatInception(Activity activity) throws IOException { 46 | super(activity); 47 | labelProbArray = new float[1][getNumLabels()]; 48 | } 49 | 50 | @Override 51 | protected String getModelPath() { 52 | // you can download this file from 53 | // https://storage.googleapis.com/download.tensorflow.org/models/tflite/inception_v3_slim_2016_android_2017_11_10.zip 54 | return "inceptionv3_slim_2016.tflite"; 55 | } 56 | 57 | @Override 58 | protected String getLabelPath() { 59 | return "labels_imagenet_slim.txt"; 60 | } 61 | 62 | @Override 63 | protected int getImageSizeX() { 64 | return 299; 65 | } 66 | 67 | @Override 68 | protected int getImageSizeY() { 69 | return 299; 70 | } 71 | 72 | @Override 73 | protected int getNumBytesPerChannel() { 74 | // a 32bit float value requires 4 bytes 75 | return 4; 76 | } 77 | 78 | @Override 79 | protected void addPixelValue(int pixelValue) { 80 | imgData.putFloat((((pixelValue >> 16) & 0xFF) - IMAGE_MEAN) / IMAGE_STD); 81 | imgData.putFloat((((pixelValue >> 8) & 0xFF) - IMAGE_MEAN) / IMAGE_STD); 82 | imgData.putFloat(((pixelValue & 0xFF) - IMAGE_MEAN) / IMAGE_STD); 83 | } 84 | 85 | @Override 86 | protected float getProbability(int labelIndex) { 87 | return labelProbArray[0][labelIndex]; 88 | } 89 | 90 | @Override 91 | protected void setProbability(int labelIndex, Number value) { 92 | labelProbArray[0][labelIndex] = value.floatValue(); 93 | } 94 | 95 | @Override 96 | protected float getNormalizedProbability(int labelIndex) { 97 | // TODO the following value isn't in [0,1] yet, but may be greater. Why? 98 | return getProbability(labelIndex); 99 | } 100 | 101 | @Override 102 | protected void runInference() { 103 | tflite.run(imgData, labelProbArray); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/java/com/example/android/tflitecamerademo/ImageClassifierQuantizedMobileNet.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2017 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package com.example.android.tflitecamerademo; 17 | 18 | import android.app.Activity; 19 | import java.io.IOException; 20 | 21 | /** 22 | * This classifier works with the quantized MobileNet model. 23 | */ 24 | public class ImageClassifierQuantizedMobileNet extends ImageClassifier { 25 | 26 | /** 27 | * An array to hold inference results, to be feed into Tensorflow Lite as outputs. 28 | * This isn't part of the super class, because we need a primitive array here. 29 | */ 30 | private byte[][] labelProbArray = null; 31 | 32 | /** 33 | * Initializes an {@code ImageClassifier}. 34 | * 35 | * @param activity 36 | */ 37 | ImageClassifierQuantizedMobileNet(Activity activity) throws IOException { 38 | super(activity); 39 | labelProbArray = new byte[1][getNumLabels()]; 40 | } 41 | 42 | @Override 43 | protected String getModelPath() { 44 | // you can download this file from 45 | // https://storage.googleapis.com/download.tensorflow.org/models/tflite/mobilenet_v1_224_android_quant_2017_11_08.zip 46 | return "mobilenet_quant_v1_224.tflite"; 47 | } 48 | 49 | @Override 50 | protected String getLabelPath() { 51 | return "labels_mobilenet_quant_v1_224.txt"; 52 | } 53 | 54 | @Override 55 | protected int getImageSizeX() { 56 | return 224; 57 | } 58 | 59 | @Override 60 | protected int getImageSizeY() { 61 | return 224; 62 | } 63 | 64 | @Override 65 | protected int getNumBytesPerChannel() { 66 | // the quantized model uses a single byte only 67 | return 1; 68 | } 69 | 70 | @Override 71 | protected void addPixelValue(int pixelValue) { 72 | imgData.put((byte) ((pixelValue >> 16) & 0xFF)); 73 | imgData.put((byte) ((pixelValue >> 8) & 0xFF)); 74 | imgData.put((byte) (pixelValue & 0xFF)); 75 | } 76 | 77 | @Override 78 | protected float getProbability(int labelIndex) { 79 | return labelProbArray[0][labelIndex]; 80 | } 81 | 82 | @Override 83 | protected void setProbability(int labelIndex, Number value) { 84 | labelProbArray[0][labelIndex] = value.byteValue(); 85 | } 86 | 87 | @Override 88 | protected float getNormalizedProbability(int labelIndex) { 89 | return (labelProbArray[0][labelIndex] & 0xff) / 255.0f; 90 | } 91 | 92 | @Override 93 | protected void runInference() { 94 | tflite.run(imgData, labelProbArray); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/jnilibs/arm64-v8a/libtensorflowlite_jni.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/src/main/jnilibs/arm64-v8a/libtensorflowlite_jni.so -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/drawable-hdpi/ic_action_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/src/main/res/drawable-hdpi/ic_action_info.png -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/drawable-hdpi/tile.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/src/main/res/drawable-hdpi/tile.9.png -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/drawable-mdpi/ic_action_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/src/main/res/drawable-mdpi/ic_action_info.png -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/drawable-xhdpi/ic_action_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/src/main/res/drawable-xhdpi/ic_action_info.png -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/drawable-xxhdpi/ic_action_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/src/main/res/drawable-xxhdpi/ic_action_info.png -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/drawable-xxhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/app/src/main/res/drawable-xxhdpi/logo.png -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/layout-land/fragment_camera2_basic.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 23 | 24 | 29 | 30 | 35 | 36 | 42 | 43 | 49 | 55 | 56 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/layout-v26/fragment_camera2_basic.xml: -------------------------------------------------------------------------------- 1 | 16 | 21 | 22 | 27 | 28 | 38 | 39 | 46 | 47 | 58 | 59 | 60 | 69 | 76 | 83 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/layout/activity_camera.xml: -------------------------------------------------------------------------------- 1 | 16 | 23 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/layout/fragment_camera2_basic.xml: -------------------------------------------------------------------------------- 1 | 16 | 21 | 22 | 27 | 28 | 38 | 39 | 46 | 47 | 58 | 59 | 60 | 69 | 76 | 83 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/values-sw600dp/template-dimens.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | @dimen/margin_huge 22 | @dimen/margin_medium 23 | 24 | 25 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/values-sw600dp/template-styles.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/values-v11/template-styles.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/values/base-strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | TfLite Camera Demo 20 | 21 | 29 | 30 | Threads: 31 | 32 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | #cc4285f4 19 | 20 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | Picture 18 | Info 19 | This sample needs camera permission. 20 | This device doesn\'t support Camera2 API. 21 | NN:On 22 | NN:Off 23 | Use NNAPI 24 | tflite 25 | NNAPI 26 | 27 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/values/template-dimens.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 4dp 22 | 8dp 23 | 16dp 24 | 32dp 25 | 64dp 26 | 27 | 28 | 29 | @dimen/margin_medium 30 | @dimen/margin_medium 31 | 32 | 33 | -------------------------------------------------------------------------------- /TFlitedemo/app/src/main/res/values/template-styles.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 34 | 35 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /TFlitedemo/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.0.1' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /TFlitedemo/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /TFlitedemo/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TFlitedemo/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /TFlitedemo/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Sep 28 09:01:41 PDT 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /TFlitedemo/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /TFlitedemo/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /TFlitedemo/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/.idea/libraries/junit_junit_4_12_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/.idea/libraries/org_hamcrest_hamcrest_core_1_3_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/TfLiteCameraDemo.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | buildToolsVersion '26.0.2' 6 | defaultConfig { 7 | applicationId "org.tensorflow.lite.demo" 8 | minSdkVersion 21 9 | targetSdkVersion 26 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 13 | 14 | } 15 | lintOptions { 16 | abortOnError false 17 | } 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | aaptOptions { 25 | noCompress "tflite" 26 | } 27 | 28 | compileOptions { 29 | sourceCompatibility JavaVersion.VERSION_1_8 30 | targetCompatibility JavaVersion.VERSION_1_8 31 | } 32 | 33 | sourceSets { 34 | main { 35 | // let gradle pack the shared library into apk 36 | jniLibs.srcDirs = ['src/main/jnilibs'] 37 | } 38 | } 39 | 40 | } 41 | 42 | repositories { 43 | maven { 44 | url 'https://google.bintray.com/tensorflow' 45 | } 46 | } 47 | 48 | // import DownloadModels task 49 | project.ext.ASSET_DIR = projectDir.toString() + '/src/main/assets' 50 | project.ext.TMP_DIR = project.buildDir.toString() + '/downloads' 51 | 52 | // Download default models; if you wish to use your own models then 53 | // place them in the "assets" directory and comment out this line. 54 | //apply from: "download-models.gradle" 55 | 56 | dependencies { 57 | compile fileTree(dir: 'libs', include: ['*.jar']) 58 | 59 | //compile 'org.tensorflow:tensorflow-lite:0.0.0-nightly' 60 | 61 | testCompile 'junit:junit:4.12' 62 | } 63 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/download-models.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * download-models.gradle 3 | * Downloads model files from ${MODEL_URL} into application's asset folder 4 | * Input: 5 | * project.ext.TMP_DIR: absolute path to hold downloaded zip files 6 | * project.ext.ASSET_DIR: absolute path to save unzipped model files 7 | * Output: 8 | * 3 model files will be downloaded into given folder of ext.ASSET_DIR 9 | */ 10 | // hard coded model files 11 | // LINT.IfChange 12 | 13 | def models = ['conv_actions_tflite.zip', 14 | 'mobilenet_ssd_tflite_v1.zip', 15 | 'mobilenet_v1_224_android_quant_2017_11_08.zip', 16 | 'coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip'] 17 | // LINT.ThenChange(//tensorflow/contrib/lite/examples/android/BUILD) 18 | 19 | // Root URL for model archives 20 | def MODEL_URL = 'https://storage.googleapis.com/download.tensorflow.org/models/tflite' 21 | 22 | buildscript { 23 | repositories { 24 | jcenter() 25 | } 26 | dependencies { 27 | classpath 'de.undercouch:gradle-download-task:3.2.0' 28 | } 29 | } 30 | 31 | import de.undercouch.gradle.tasks.download.Download 32 | task downloadFile(type: Download){ 33 | for (f in models) { 34 | def modelUrl = MODEL_URL + "/" + f 35 | println "Downloading ${f} from ${modelUrl}" 36 | src modelUrl 37 | } 38 | 39 | dest new File(project.ext.TMP_DIR) 40 | overwrite true 41 | } 42 | 43 | task extractModels(type: Copy) { 44 | for (f in models) { 45 | def localFile = f.split("/")[-1] 46 | from zipTree(project.ext.TMP_DIR + '/' + localFile) 47 | } 48 | 49 | into file(project.ext.ASSET_DIR) 50 | fileMode 0644 51 | exclude '**/LICENSE' 52 | 53 | def needDownload = false 54 | for (f in models) { 55 | def localFile = f.split("/")[-1] 56 | if (!(new File(project.ext.TMP_DIR + '/' + localFile)).exists()) { 57 | needDownload = true 58 | } 59 | } 60 | 61 | if (needDownload) { 62 | dependsOn downloadFile 63 | } 64 | } 65 | 66 | tasks.whenTaskAdded { task -> 67 | if (task.name == 'assembleDebug') { 68 | task.dependsOn 'extractModels' 69 | } 70 | if (task.name == 'assembleRelease') { 71 | task.dependsOn 'extractModels' 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/libs/libtensorflowlite.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TfLiteCameraDemo/app/libs/libtensorflowlite.jar -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 36 | 37 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/assets/coco_labels_list.txt: -------------------------------------------------------------------------------- 1 | ??? 2 | person 3 | bicycle 4 | car 5 | motorcycle 6 | airplane 7 | bus 8 | train 9 | truck 10 | boat 11 | traffic light 12 | fire hydrant 13 | ??? 14 | stop sign 15 | parking meter 16 | bench 17 | bird 18 | cat 19 | dog 20 | horse 21 | sheep 22 | cow 23 | elephant 24 | bear 25 | zebra 26 | giraffe 27 | ??? 28 | backpack 29 | umbrella 30 | ??? 31 | ??? 32 | handbag 33 | tie 34 | suitcase 35 | frisbee 36 | skis 37 | snowboard 38 | sports ball 39 | kite 40 | baseball bat 41 | baseball glove 42 | skateboard 43 | surfboard 44 | tennis racket 45 | bottle 46 | ??? 47 | wine glass 48 | cup 49 | fork 50 | knife 51 | spoon 52 | bowl 53 | banana 54 | apple 55 | sandwich 56 | orange 57 | broccoli 58 | carrot 59 | hot dog 60 | pizza 61 | donut 62 | cake 63 | chair 64 | couch 65 | potted plant 66 | bed 67 | ??? 68 | dining table 69 | ??? 70 | ??? 71 | toilet 72 | ??? 73 | tv 74 | laptop 75 | mouse 76 | remote 77 | keyboard 78 | cell phone 79 | microwave 80 | oven 81 | toaster 82 | sink 83 | refrigerator 84 | ??? 85 | book 86 | clock 87 | vase 88 | scissors 89 | teddy bear 90 | hair drier 91 | toothbrush 92 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/assets/conv_actions_labels.txt: -------------------------------------------------------------------------------- 1 | _silence_ 2 | _unknown_ 3 | yes 4 | no 5 | up 6 | down 7 | left 8 | right 9 | on 10 | off 11 | stop 12 | go -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/assets/download.sh: -------------------------------------------------------------------------------- 1 | wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/conv_actions_tflite.zip 2 | wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/mobilenet_ssd_tflite_v1.zip 3 | wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/mobilenet_v1_224_android_quant_2017_11_08.zip 4 | wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/assets/labels_list.txt: -------------------------------------------------------------------------------- 1 | 0:background 2 | 1:hat 3 | 2:attention 4 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/AutoFitTextureView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The TensorFlow Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.tensorflow.demo; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.view.TextureView; 22 | 23 | /** 24 | * A {@link TextureView} that can be adjusted to a specified aspect ratio. 25 | */ 26 | public class AutoFitTextureView extends TextureView { 27 | private int ratioWidth = 0; 28 | private int ratioHeight = 0; 29 | 30 | public AutoFitTextureView(final Context context) { 31 | this(context, null); 32 | } 33 | 34 | public AutoFitTextureView(final Context context, final AttributeSet attrs) { 35 | this(context, attrs, 0); 36 | } 37 | 38 | public AutoFitTextureView(final Context context, final AttributeSet attrs, final int defStyle) { 39 | super(context, attrs, defStyle); 40 | } 41 | 42 | /** 43 | * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio 44 | * calculated from the parameters. Note that the actual sizes of parameters don't matter, that 45 | * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result. 46 | * 47 | * @param width Relative horizontal size 48 | * @param height Relative vertical size 49 | */ 50 | public void setAspectRatio(final int width, final int height) { 51 | if (width < 0 || height < 0) { 52 | throw new IllegalArgumentException("Size cannot be negative."); 53 | } 54 | ratioWidth = width; 55 | ratioHeight = height; 56 | requestLayout(); 57 | } 58 | 59 | @Override 60 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 61 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 62 | final int width = MeasureSpec.getSize(widthMeasureSpec); 63 | final int height = MeasureSpec.getSize(heightMeasureSpec); 64 | if (0 == ratioWidth || 0 == ratioHeight) { 65 | setMeasuredDimension(width, height); 66 | } else { 67 | if (width < height * ratioWidth / ratioHeight) { 68 | setMeasuredDimension(width, width * ratioHeight / ratioWidth); 69 | } else { 70 | setMeasuredDimension(height * ratioWidth / ratioHeight, height); 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/Classifier.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package org.tensorflow.demo; 17 | 18 | import android.graphics.Bitmap; 19 | import android.graphics.RectF; 20 | import java.util.List; 21 | 22 | /** 23 | * Generic interface for interacting with different recognition engines. 24 | */ 25 | public interface Classifier { 26 | /** 27 | * An immutable result returned by a Classifier describing what was recognized. 28 | */ 29 | public class Recognition { 30 | /** 31 | * A unique identifier for what has been recognized. Specific to the class, not the instance of 32 | * the object. 33 | */ 34 | private final String id; 35 | 36 | /** 37 | * Display name for the recognition. 38 | */ 39 | private final String title; 40 | 41 | /** 42 | * A sortable score for how good the recognition is relative to others. Higher should be better. 43 | */ 44 | private final Float confidence; 45 | 46 | /** Optional location within the source image for the location of the recognized object. */ 47 | private RectF location; 48 | 49 | public Recognition( 50 | final String id, final String title, final Float confidence, final RectF location) { 51 | this.id = id; 52 | this.title = title; 53 | this.confidence = confidence; 54 | this.location = location; 55 | } 56 | 57 | public String getId() { 58 | return id; 59 | } 60 | 61 | public String getTitle() { 62 | return title; 63 | } 64 | 65 | public Float getConfidence() { 66 | return confidence; 67 | } 68 | 69 | public RectF getLocation() { 70 | return new RectF(location); 71 | } 72 | 73 | public void setLocation(RectF location) { 74 | this.location = location; 75 | } 76 | 77 | @Override 78 | public String toString() { 79 | String resultString = ""; 80 | if (id != null) { 81 | resultString += "[" + id + "] "; 82 | } 83 | 84 | if (title != null) { 85 | resultString += title + " "; 86 | } 87 | 88 | if (confidence != null) { 89 | resultString += String.format("(%.1f%%) ", confidence * 100.0f); 90 | } 91 | 92 | if (location != null) { 93 | resultString += location + " "; 94 | } 95 | 96 | return resultString.trim(); 97 | } 98 | } 99 | 100 | List recognizeImage(Bitmap bitmap); 101 | 102 | void enableStatLogging(final boolean debug); 103 | 104 | String getStatString(); 105 | 106 | void close(); 107 | } 108 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/ClassifierActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The TensorFlow Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.tensorflow.demo; 18 | 19 | import android.graphics.Bitmap; 20 | import android.graphics.Bitmap.Config; 21 | import android.graphics.Canvas; 22 | import android.graphics.Matrix; 23 | import android.graphics.Paint; 24 | import android.graphics.Typeface; 25 | import android.media.ImageReader.OnImageAvailableListener; 26 | import android.os.SystemClock; 27 | import android.util.Size; 28 | import android.util.TypedValue; 29 | import java.util.List; 30 | import java.util.Vector; 31 | import org.tensorflow.demo.OverlayView.DrawCallback; 32 | import org.tensorflow.demo.env.BorderedText; 33 | import org.tensorflow.demo.env.ImageUtils; 34 | import org.tensorflow.demo.env.Logger; 35 | import org.tensorflow.lite.demo.R; // Explicit import needed for internal Google builds. 36 | 37 | public class ClassifierActivity extends CameraActivity implements OnImageAvailableListener { 38 | private static final Logger LOGGER = new Logger(); 39 | 40 | protected static final boolean SAVE_PREVIEW_BITMAP = false; 41 | 42 | private ResultsView resultsView; 43 | 44 | private Bitmap rgbFrameBitmap = null; 45 | private Bitmap croppedBitmap = null; 46 | private Bitmap cropCopyBitmap = null; 47 | 48 | private long lastProcessingTimeMs; 49 | 50 | // These are the settings for the original v1 Inception model. If you want to 51 | // use a model that's been produced from the TensorFlow for Poets codelab, 52 | // you'll need to set IMAGE_SIZE = 299, IMAGE_MEAN = 128, IMAGE_STD = 128, 53 | // INPUT_NAME = "Mul", and OUTPUT_NAME = "final_result". 54 | // You'll also need to update the MODEL_FILE and LABEL_FILE paths to point to 55 | // the ones you produced. 56 | // 57 | // To use v3 Inception model, strip the DecodeJpeg Op from your retrained 58 | // model first: 59 | // 60 | // python strip_unused.py \ 61 | // --input_graph= \ 62 | // --output_graph= \ 63 | // --input_node_names="Mul" \ 64 | // --output_node_names="final_result" \ 65 | // --input_binary=true 66 | private static final int INPUT_SIZE = 224; 67 | 68 | private static final String MODEL_FILE = "mobilenet_quant_v1_224.tflite"; 69 | private static final String LABEL_FILE = "labels_mobilenet_quant_v1_224.txt"; 70 | 71 | private static final boolean MAINTAIN_ASPECT = true; 72 | 73 | private static final Size DESIRED_PREVIEW_SIZE = new Size(640, 480); 74 | 75 | 76 | private Integer sensorOrientation; 77 | private Classifier classifier; 78 | private Matrix frameToCropTransform; 79 | private Matrix cropToFrameTransform; 80 | 81 | private BorderedText borderedText; 82 | 83 | @Override 84 | protected int getLayoutId() { 85 | return R.layout.camera_connection_fragment; 86 | } 87 | 88 | @Override 89 | protected Size getDesiredPreviewFrameSize() { 90 | return DESIRED_PREVIEW_SIZE; 91 | } 92 | 93 | private static final float TEXT_SIZE_DIP = 10; 94 | 95 | @Override 96 | public void onPreviewSizeChosen(final Size size, final int rotation) { 97 | final float textSizePx = TypedValue.applyDimension( 98 | TypedValue.COMPLEX_UNIT_DIP, TEXT_SIZE_DIP, getResources().getDisplayMetrics()); 99 | borderedText = new BorderedText(textSizePx); 100 | borderedText.setTypeface(Typeface.MONOSPACE); 101 | 102 | classifier = TFLiteImageClassifier.create(getAssets(), MODEL_FILE, LABEL_FILE, INPUT_SIZE); 103 | 104 | previewWidth = size.getWidth(); 105 | previewHeight = size.getHeight(); 106 | 107 | sensorOrientation = rotation - getScreenOrientation(); 108 | LOGGER.i("Camera orientation relative to screen canvas: %d", sensorOrientation); 109 | 110 | LOGGER.i("Initializing at size %dx%d", previewWidth, previewHeight); 111 | rgbFrameBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888); 112 | croppedBitmap = Bitmap.createBitmap(INPUT_SIZE, INPUT_SIZE, Config.ARGB_8888); 113 | 114 | frameToCropTransform = ImageUtils.getTransformationMatrix( 115 | previewWidth, previewHeight, 116 | INPUT_SIZE, INPUT_SIZE, 117 | sensorOrientation, MAINTAIN_ASPECT); 118 | 119 | cropToFrameTransform = new Matrix(); 120 | frameToCropTransform.invert(cropToFrameTransform); 121 | 122 | addCallback( 123 | new DrawCallback() { 124 | @Override 125 | public void drawCallback(final Canvas canvas) { 126 | renderDebug(canvas); 127 | } 128 | }); 129 | } 130 | 131 | @Override 132 | protected void processImage() { 133 | rgbFrameBitmap.setPixels(getRgbBytes(), 0, previewWidth, 0, 0, previewWidth, previewHeight); 134 | final Canvas canvas = new Canvas(croppedBitmap); 135 | canvas.drawBitmap(rgbFrameBitmap, frameToCropTransform, null); 136 | 137 | // For examining the actual TF input. 138 | if (SAVE_PREVIEW_BITMAP) { 139 | ImageUtils.saveBitmap(croppedBitmap); 140 | } 141 | runInBackground( 142 | new Runnable() { 143 | @Override 144 | public void run() { 145 | final long startTime = SystemClock.uptimeMillis(); 146 | final List results = classifier.recognizeImage(croppedBitmap); 147 | lastProcessingTimeMs = SystemClock.uptimeMillis() - startTime; 148 | LOGGER.i("Detect: %s", results); 149 | cropCopyBitmap = Bitmap.createBitmap(croppedBitmap); 150 | if (resultsView == null) { 151 | resultsView = (ResultsView) findViewById(R.id.results); 152 | } 153 | resultsView.setDuration(lastProcessingTimeMs); 154 | resultsView.setResults(results); 155 | requestRender(); 156 | readyForNextImage(); 157 | } 158 | }); 159 | } 160 | 161 | @Override 162 | public void onSetDebug(boolean debug) { 163 | classifier.enableStatLogging(debug); 164 | } 165 | 166 | private void renderDebug(final Canvas canvas) { 167 | if (!isDebug()) { 168 | return; 169 | } 170 | final Bitmap copy = cropCopyBitmap; 171 | if (copy != null) { 172 | final Matrix matrix = new Matrix(); 173 | final float scaleFactor = 2; 174 | matrix.postScale(scaleFactor, scaleFactor); 175 | matrix.postTranslate( 176 | canvas.getWidth() - copy.getWidth() * scaleFactor, 177 | canvas.getHeight() - copy.getHeight() * scaleFactor); 178 | canvas.drawBitmap(copy, matrix, new Paint()); 179 | 180 | final Vector lines = new Vector(); 181 | if (classifier != null) { 182 | String statString = classifier.getStatString(); 183 | String[] statLines = statString.split("\n"); 184 | for (String line : statLines) { 185 | lines.add(line); 186 | } 187 | } 188 | 189 | lines.add("Frame: " + previewWidth + "x" + previewHeight); 190 | lines.add("Crop: " + copy.getWidth() + "x" + copy.getHeight()); 191 | lines.add("View: " + canvas.getWidth() + "x" + canvas.getHeight()); 192 | lines.add("Rotation: " + sensorOrientation); 193 | lines.add("Inference time: " + lastProcessingTimeMs + "ms"); 194 | 195 | borderedText.drawLines(canvas, 10, canvas.getHeight() - 10, lines); 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/DetectorActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The TensorFlow Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.tensorflow.demo; 18 | 19 | import android.graphics.Bitmap; 20 | import android.graphics.Bitmap.Config; 21 | import android.graphics.Canvas; 22 | import android.graphics.Color; 23 | import android.graphics.Matrix; 24 | import android.graphics.Paint; 25 | import android.graphics.Paint.Style; 26 | import android.graphics.RectF; 27 | import android.graphics.Typeface; 28 | import android.media.ImageReader.OnImageAvailableListener; 29 | import android.os.SystemClock; 30 | import android.util.Size; 31 | import android.util.TypedValue; 32 | import android.widget.Toast; 33 | import java.io.IOException; 34 | import java.util.LinkedList; 35 | import java.util.List; 36 | import java.util.Vector; 37 | import org.tensorflow.demo.OverlayView.DrawCallback; 38 | import org.tensorflow.demo.env.BorderedText; 39 | import org.tensorflow.demo.env.ImageUtils; 40 | import org.tensorflow.demo.env.Logger; 41 | import org.tensorflow.demo.tracking.MultiBoxTracker; 42 | import org.tensorflow.lite.demo.R; // Explicit import needed for internal Google builds. 43 | 44 | /** 45 | * An activity that uses a TensorFlowMultiBoxDetector and ObjectTracker to detect and then track 46 | * objects. 47 | */ 48 | public class DetectorActivity extends CameraActivity implements OnImageAvailableListener { 49 | private static final Logger LOGGER = new Logger(); 50 | 51 | // Configuration values for the prepackaged SSD model. 52 | private static final int TF_OD_API_INPUT_SIZE = 300; 53 | private static final boolean TF_OD_API_IS_QUANTIZED = false; 54 | private static final String TF_OD_API_MODEL_FILE = "detect.tflite"; 55 | private static final String TF_OD_API_LABELS_FILE = "file:///android_asset/labels_list.txt"; 56 | 57 | // Which detection model to use: by default uses Tensorflow Object Detection API frozen 58 | // checkpoints. 59 | private enum DetectorMode { 60 | TF_OD_API; 61 | } 62 | 63 | private static final DetectorMode MODE = DetectorMode.TF_OD_API; 64 | 65 | // Minimum detection confidence to track a detection. 66 | private static final float MINIMUM_CONFIDENCE_TF_OD_API = 0.6f; 67 | 68 | private static final boolean MAINTAIN_ASPECT = false; 69 | 70 | private static final Size DESIRED_PREVIEW_SIZE = new Size(640, 480); 71 | 72 | private static final boolean SAVE_PREVIEW_BITMAP = false; 73 | private static final float TEXT_SIZE_DIP = 10; 74 | 75 | private Integer sensorOrientation; 76 | 77 | private Classifier detector; 78 | 79 | private long lastProcessingTimeMs; 80 | private Bitmap rgbFrameBitmap = null; 81 | private Bitmap croppedBitmap = null; 82 | private Bitmap cropCopyBitmap = null; 83 | 84 | private boolean computingDetection = false; 85 | 86 | private long timestamp = 0; 87 | 88 | private Matrix frameToCropTransform; 89 | private Matrix cropToFrameTransform; 90 | 91 | private MultiBoxTracker tracker; 92 | 93 | private byte[] luminanceCopy; 94 | 95 | private BorderedText borderedText; 96 | @Override 97 | public void onPreviewSizeChosen(final Size size, final int rotation) { 98 | final float textSizePx = 99 | TypedValue.applyDimension( 100 | TypedValue.COMPLEX_UNIT_DIP, TEXT_SIZE_DIP, getResources().getDisplayMetrics()); 101 | borderedText = new BorderedText(textSizePx); 102 | borderedText.setTypeface(Typeface.MONOSPACE); 103 | 104 | tracker = new MultiBoxTracker(this); 105 | 106 | int cropSize = TF_OD_API_INPUT_SIZE; 107 | 108 | try { 109 | detector = 110 | TFLiteObjectDetectionAPIModel.create( 111 | getAssets(), 112 | TF_OD_API_MODEL_FILE, 113 | TF_OD_API_LABELS_FILE, 114 | TF_OD_API_INPUT_SIZE, 115 | TF_OD_API_IS_QUANTIZED); 116 | cropSize = TF_OD_API_INPUT_SIZE; 117 | } catch (final IOException e) { 118 | LOGGER.e("Exception initializing classifier!", e); 119 | Toast toast = 120 | Toast.makeText( 121 | getApplicationContext(), "Classifier could not be initialized", Toast.LENGTH_SHORT); 122 | toast.show(); 123 | finish(); 124 | } 125 | 126 | 127 | previewWidth = size.getWidth(); 128 | previewHeight = size.getHeight(); 129 | 130 | sensorOrientation = rotation - getScreenOrientation(); 131 | LOGGER.i("Camera orientation relative to screen canvas: %d", sensorOrientation); 132 | 133 | LOGGER.i("Initializing at size %dx%d", previewWidth, previewHeight); 134 | rgbFrameBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Config.ARGB_8888); 135 | croppedBitmap = Bitmap.createBitmap(cropSize, cropSize, Config.ARGB_8888); 136 | 137 | frameToCropTransform = 138 | ImageUtils.getTransformationMatrix( 139 | previewWidth, previewHeight, 140 | cropSize, cropSize, 141 | sensorOrientation, MAINTAIN_ASPECT); 142 | 143 | cropToFrameTransform = new Matrix(); 144 | frameToCropTransform.invert(cropToFrameTransform); 145 | 146 | trackingOverlay = (OverlayView) findViewById(R.id.tracking_overlay); 147 | trackingOverlay.addCallback( 148 | new DrawCallback() { 149 | @Override 150 | public void drawCallback(final Canvas canvas) { 151 | tracker.draw(canvas); 152 | if (isDebug()) { 153 | tracker.drawDebug(canvas); 154 | } 155 | } 156 | }); 157 | 158 | addCallback( 159 | new DrawCallback() { 160 | @Override 161 | public void drawCallback(final Canvas canvas) { 162 | if (!isDebug()) { 163 | return; 164 | } 165 | final Bitmap copy = cropCopyBitmap; 166 | if (copy == null) { 167 | return; 168 | } 169 | 170 | final int backgroundColor = Color.argb(100, 0, 0, 0); 171 | canvas.drawColor(backgroundColor); 172 | 173 | final Matrix matrix = new Matrix(); 174 | final float scaleFactor = 2; 175 | matrix.postScale(scaleFactor, scaleFactor); 176 | matrix.postTranslate( 177 | canvas.getWidth() - copy.getWidth() * scaleFactor, 178 | canvas.getHeight() - copy.getHeight() * scaleFactor); 179 | canvas.drawBitmap(copy, matrix, new Paint()); 180 | 181 | final Vector lines = new Vector(); 182 | if (detector != null) { 183 | final String statString = detector.getStatString(); 184 | final String[] statLines = statString.split("\n"); 185 | for (final String line : statLines) { 186 | lines.add(line); 187 | } 188 | } 189 | lines.add(""); 190 | 191 | lines.add("Frame: " + previewWidth + "x" + previewHeight); 192 | lines.add("Crop: " + copy.getWidth() + "x" + copy.getHeight()); 193 | lines.add("View: " + canvas.getWidth() + "x" + canvas.getHeight()); 194 | lines.add("Rotation: " + sensorOrientation); 195 | lines.add("Inference time: " + lastProcessingTimeMs + "ms"); 196 | 197 | borderedText.drawLines(canvas, 10, canvas.getHeight() - 10, lines); 198 | } 199 | }); 200 | } 201 | 202 | OverlayView trackingOverlay; 203 | 204 | @Override 205 | protected void processImage() { 206 | ++timestamp; 207 | final long currTimestamp = timestamp; 208 | byte[] originalLuminance = getLuminance(); 209 | tracker.onFrame( 210 | previewWidth, 211 | previewHeight, 212 | getLuminanceStride(), 213 | sensorOrientation, 214 | originalLuminance, 215 | timestamp); 216 | trackingOverlay.postInvalidate(); 217 | 218 | // No mutex needed as this method is not reentrant. 219 | if (computingDetection) { 220 | readyForNextImage(); 221 | return; 222 | } 223 | computingDetection = true; 224 | LOGGER.i("Preparing image " + currTimestamp + " for detection in bg thread."); 225 | 226 | rgbFrameBitmap.setPixels(getRgbBytes(), 0, previewWidth, 0, 0, previewWidth, previewHeight); 227 | 228 | if (luminanceCopy == null) { 229 | luminanceCopy = new byte[originalLuminance.length]; 230 | } 231 | System.arraycopy(originalLuminance, 0, luminanceCopy, 0, originalLuminance.length); 232 | readyForNextImage(); 233 | 234 | final Canvas canvas = new Canvas(croppedBitmap); 235 | canvas.drawBitmap(rgbFrameBitmap, frameToCropTransform, null); 236 | // For examining the actual TF input. 237 | if (SAVE_PREVIEW_BITMAP) { 238 | ImageUtils.saveBitmap(croppedBitmap); 239 | } 240 | 241 | runInBackground( 242 | new Runnable() { 243 | @Override 244 | public void run() { 245 | LOGGER.i("Running detection on image " + currTimestamp); 246 | final long startTime = SystemClock.uptimeMillis(); 247 | final List results = detector.recognizeImage(croppedBitmap); 248 | lastProcessingTimeMs = SystemClock.uptimeMillis() - startTime; 249 | 250 | cropCopyBitmap = Bitmap.createBitmap(croppedBitmap); 251 | final Canvas canvas = new Canvas(cropCopyBitmap); 252 | final Paint paint = new Paint(); 253 | paint.setColor(Color.RED); 254 | paint.setStyle(Style.STROKE); 255 | paint.setStrokeWidth(2.0f); 256 | 257 | float minimumConfidence = MINIMUM_CONFIDENCE_TF_OD_API; 258 | switch (MODE) { 259 | case TF_OD_API: 260 | minimumConfidence = MINIMUM_CONFIDENCE_TF_OD_API; 261 | break; 262 | } 263 | 264 | final List mappedRecognitions = 265 | new LinkedList(); 266 | 267 | for (final Classifier.Recognition result : results) { 268 | final RectF location = result.getLocation(); 269 | if (location != null && result.getConfidence() >= minimumConfidence) { 270 | canvas.drawRect(location, paint); 271 | 272 | cropToFrameTransform.mapRect(location); 273 | result.setLocation(location); 274 | mappedRecognitions.add(result); 275 | } 276 | } 277 | 278 | tracker.trackResults(mappedRecognitions, luminanceCopy, currTimestamp); 279 | trackingOverlay.postInvalidate(); 280 | 281 | requestRender(); 282 | computingDetection = false; 283 | } 284 | }); 285 | } 286 | 287 | @Override 288 | protected int getLayoutId() { 289 | return R.layout.camera_connection_fragment_tracking; 290 | } 291 | 292 | @Override 293 | protected Size getDesiredPreviewFrameSize() { 294 | return DESIRED_PREVIEW_SIZE; 295 | } 296 | 297 | @Override 298 | public void onSetDebug(final boolean debug) { 299 | detector.enableStatLogging(debug); 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/LegacyCameraConnectionFragment.java: -------------------------------------------------------------------------------- 1 | package org.tensorflow.demo; 2 | 3 | /* 4 | * Copyright 2017 The TensorFlow Authors. All Rights Reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.app.Fragment; 20 | import android.graphics.SurfaceTexture; 21 | import android.hardware.Camera; 22 | import android.hardware.Camera.CameraInfo; 23 | import android.os.Bundle; 24 | import android.os.Handler; 25 | import android.os.HandlerThread; 26 | import android.util.Size; 27 | import android.util.SparseIntArray; 28 | import android.view.LayoutInflater; 29 | import android.view.Surface; 30 | import android.view.TextureView; 31 | import android.view.View; 32 | import android.view.ViewGroup; 33 | import java.io.IOException; 34 | import java.util.List; 35 | import org.tensorflow.demo.env.ImageUtils; 36 | import org.tensorflow.demo.env.Logger; 37 | import org.tensorflow.lite.demo.R; // Explicit import needed for internal Google builds. 38 | 39 | public class LegacyCameraConnectionFragment extends Fragment { 40 | private Camera camera; 41 | private static final Logger LOGGER = new Logger(); 42 | private Camera.PreviewCallback imageListener; 43 | private Size desiredSize; 44 | 45 | /** 46 | * The layout identifier to inflate for this Fragment. 47 | */ 48 | private int layout; 49 | 50 | public LegacyCameraConnectionFragment( 51 | final Camera.PreviewCallback imageListener, final int layout, final Size desiredSize) { 52 | this.imageListener = imageListener; 53 | this.layout = layout; 54 | this.desiredSize = desiredSize; 55 | } 56 | 57 | /** 58 | * Conversion from screen rotation to JPEG orientation. 59 | */ 60 | private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); 61 | 62 | static { 63 | ORIENTATIONS.append(Surface.ROTATION_0, 90); 64 | ORIENTATIONS.append(Surface.ROTATION_90, 0); 65 | ORIENTATIONS.append(Surface.ROTATION_180, 270); 66 | ORIENTATIONS.append(Surface.ROTATION_270, 180); 67 | } 68 | 69 | /** 70 | * {@link android.view.TextureView.SurfaceTextureListener} handles several lifecycle events on a 71 | * {@link TextureView}. 72 | */ 73 | private final TextureView.SurfaceTextureListener surfaceTextureListener = 74 | new TextureView.SurfaceTextureListener() { 75 | @Override 76 | public void onSurfaceTextureAvailable( 77 | final SurfaceTexture texture, final int width, final int height) { 78 | 79 | int index = getCameraId(); 80 | camera = Camera.open(index); 81 | 82 | try { 83 | Camera.Parameters parameters = camera.getParameters(); 84 | List focusModes = parameters.getSupportedFocusModes(); 85 | if (focusModes != null 86 | && focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { 87 | parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 88 | } 89 | List cameraSizes = parameters.getSupportedPreviewSizes(); 90 | Size[] sizes = new Size[cameraSizes.size()]; 91 | int i = 0; 92 | for (Camera.Size size : cameraSizes) { 93 | sizes[i++] = new Size(size.width, size.height); 94 | } 95 | Size previewSize = 96 | CameraConnectionFragment.chooseOptimalSize( 97 | sizes, desiredSize.getWidth(), desiredSize.getHeight()); 98 | parameters.setPreviewSize(previewSize.getWidth(), previewSize.getHeight()); 99 | camera.setDisplayOrientation(90); 100 | camera.setParameters(parameters); 101 | camera.setPreviewTexture(texture); 102 | } catch (IOException exception) { 103 | camera.release(); 104 | } 105 | 106 | camera.setPreviewCallbackWithBuffer(imageListener); 107 | Camera.Size s = camera.getParameters().getPreviewSize(); 108 | camera.addCallbackBuffer(new byte[ImageUtils.getYUVByteSize(s.height, s.width)]); 109 | 110 | textureView.setAspectRatio(s.height, s.width); 111 | 112 | camera.startPreview(); 113 | } 114 | 115 | @Override 116 | public void onSurfaceTextureSizeChanged( 117 | final SurfaceTexture texture, final int width, final int height) {} 118 | 119 | @Override 120 | public boolean onSurfaceTextureDestroyed(final SurfaceTexture texture) { 121 | return true; 122 | } 123 | 124 | @Override 125 | public void onSurfaceTextureUpdated(final SurfaceTexture texture) {} 126 | }; 127 | 128 | /** 129 | * An {@link AutoFitTextureView} for camera preview. 130 | */ 131 | private AutoFitTextureView textureView; 132 | 133 | /** 134 | * An additional thread for running tasks that shouldn't block the UI. 135 | */ 136 | private HandlerThread backgroundThread; 137 | 138 | @Override 139 | public View onCreateView( 140 | final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { 141 | return inflater.inflate(layout, container, false); 142 | } 143 | 144 | @Override 145 | public void onViewCreated(final View view, final Bundle savedInstanceState) { 146 | textureView = (AutoFitTextureView) view.findViewById(R.id.texture); 147 | } 148 | 149 | @Override 150 | public void onActivityCreated(final Bundle savedInstanceState) { 151 | super.onActivityCreated(savedInstanceState); 152 | } 153 | 154 | @Override 155 | public void onResume() { 156 | super.onResume(); 157 | startBackgroundThread(); 158 | // When the screen is turned off and turned back on, the SurfaceTexture is already 159 | // available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open 160 | // a camera and start preview from here (otherwise, we wait until the surface is ready in 161 | // the SurfaceTextureListener). 162 | 163 | if (textureView.isAvailable()) { 164 | camera.startPreview(); 165 | } else { 166 | textureView.setSurfaceTextureListener(surfaceTextureListener); 167 | } 168 | } 169 | 170 | @Override 171 | public void onPause() { 172 | stopCamera(); 173 | stopBackgroundThread(); 174 | super.onPause(); 175 | } 176 | 177 | /** 178 | * Starts a background thread and its {@link Handler}. 179 | */ 180 | private void startBackgroundThread() { 181 | backgroundThread = new HandlerThread("CameraBackground"); 182 | backgroundThread.start(); 183 | } 184 | 185 | /** 186 | * Stops the background thread and its {@link Handler}. 187 | */ 188 | private void stopBackgroundThread() { 189 | backgroundThread.quitSafely(); 190 | try { 191 | backgroundThread.join(); 192 | backgroundThread = null; 193 | } catch (final InterruptedException e) { 194 | LOGGER.e(e, "Exception!"); 195 | } 196 | } 197 | 198 | protected void stopCamera() { 199 | if (camera != null) { 200 | camera.stopPreview(); 201 | camera.setPreviewCallback(null); 202 | camera.release(); 203 | camera = null; 204 | } 205 | } 206 | 207 | private int getCameraId() { 208 | CameraInfo ci = new CameraInfo(); 209 | for (int i = 0; i < Camera.getNumberOfCameras(); i++) { 210 | Camera.getCameraInfo(i, ci); 211 | if (ci.facing == CameraInfo.CAMERA_FACING_BACK) 212 | return i; 213 | } 214 | return -1; // No camera found 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/OverlayView.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package org.tensorflow.demo; 17 | 18 | import android.content.Context; 19 | import android.graphics.Canvas; 20 | import android.util.AttributeSet; 21 | import android.view.View; 22 | import java.util.LinkedList; 23 | import java.util.List; 24 | 25 | /** 26 | * A simple View providing a render callback to other classes. 27 | */ 28 | public class OverlayView extends View { 29 | private final List callbacks = new LinkedList(); 30 | 31 | public OverlayView(final Context context, final AttributeSet attrs) { 32 | super(context, attrs); 33 | } 34 | 35 | /** 36 | * Interface defining the callback for client classes. 37 | */ 38 | public interface DrawCallback { 39 | public void drawCallback(final Canvas canvas); 40 | } 41 | 42 | public void addCallback(final DrawCallback callback) { 43 | callbacks.add(callback); 44 | } 45 | 46 | @Override 47 | public synchronized void draw(final Canvas canvas) { 48 | for (final DrawCallback callback : callbacks) { 49 | callback.drawCallback(canvas); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/RecognitionScoreView.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package org.tensorflow.demo; 17 | 18 | import android.content.Context; 19 | import android.graphics.Canvas; 20 | import android.graphics.Paint; 21 | import android.util.AttributeSet; 22 | import android.util.TypedValue; 23 | import android.view.View; 24 | import java.util.List; 25 | import org.tensorflow.demo.Classifier.Recognition; 26 | 27 | public class RecognitionScoreView extends View implements ResultsView { 28 | private static final float TEXT_SIZE_DIP = 24; 29 | private List results; 30 | private final float textSizePx; 31 | private final Paint fgPaint; 32 | private final Paint bgPaint; 33 | private long duration; 34 | 35 | public RecognitionScoreView(final Context context, final AttributeSet set) { 36 | super(context, set); 37 | 38 | textSizePx = 39 | TypedValue.applyDimension( 40 | TypedValue.COMPLEX_UNIT_DIP, TEXT_SIZE_DIP, getResources().getDisplayMetrics()); 41 | fgPaint = new Paint(); 42 | fgPaint.setTextSize(textSizePx); 43 | 44 | bgPaint = new Paint(); 45 | bgPaint.setColor(0xcc4285f4); 46 | } 47 | 48 | @Override 49 | public void setResults(final List results) { 50 | this.results = results; 51 | postInvalidate(); 52 | } 53 | 54 | @Override 55 | public void setDuration(long duration) { 56 | this.duration = duration; 57 | } 58 | 59 | @Override 60 | public void onDraw(final Canvas canvas) { 61 | final int x = 10; 62 | int y = (int) (fgPaint.getTextSize() * 1.5f); 63 | 64 | canvas.drawPaint(bgPaint); 65 | 66 | if (results != null) { 67 | canvas.drawText("Inference time:"+duration + " ms", x, y, fgPaint); 68 | y += fgPaint.getTextSize() * 1.5f; 69 | for (final Recognition recog : results) { 70 | canvas.drawText(recog.getTitle() + ": " + recog.getConfidence(), x, y, fgPaint); 71 | y += (int) (fgPaint.getTextSize() * 1.5f); 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/RecognizeCommands.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 The TensorFlow Authors. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.tensorflow.demo; 18 | 19 | import android.util.Log; 20 | import android.util.Pair; 21 | import java.util.ArrayDeque; 22 | import java.util.ArrayList; 23 | import java.util.Arrays; 24 | import java.util.Deque; 25 | import java.util.List; 26 | 27 | /** Reads in results from an instantaneous audio recognition model and smoothes them over time. */ 28 | public class RecognizeCommands { 29 | // Configuration settings. 30 | private List labels = new ArrayList(); 31 | private long averageWindowDurationMs; 32 | private float detectionThreshold; 33 | private int suppressionMs; 34 | private int minimumCount; 35 | private long minimumTimeBetweenSamplesMs; 36 | 37 | // Working variables. 38 | private Deque> previousResults = new ArrayDeque>(); 39 | private String previousTopLabel; 40 | private int labelsCount; 41 | private long previousTopLabelTime; 42 | private float previousTopLabelScore; 43 | 44 | private static final String SILENCE_LABEL = "_silence_"; 45 | private static final long MINIMUM_TIME_FRACTION = 4; 46 | 47 | public RecognizeCommands( 48 | List inLabels, 49 | long inAverageWindowDurationMs, 50 | float inDetectionThreshold, 51 | int inSuppressionMS, 52 | int inMinimumCount, 53 | long inMinimumTimeBetweenSamplesMS) { 54 | labels = inLabels; 55 | averageWindowDurationMs = inAverageWindowDurationMs; 56 | detectionThreshold = inDetectionThreshold; 57 | suppressionMs = inSuppressionMS; 58 | minimumCount = inMinimumCount; 59 | labelsCount = inLabels.size(); 60 | previousTopLabel = SILENCE_LABEL; 61 | previousTopLabelTime = Long.MIN_VALUE; 62 | previousTopLabelScore = 0.0f; 63 | minimumTimeBetweenSamplesMs = inMinimumTimeBetweenSamplesMS; 64 | } 65 | 66 | /** Holds information about what's been recognized. */ 67 | public static class RecognitionResult { 68 | public final String foundCommand; 69 | public final float score; 70 | public final boolean isNewCommand; 71 | 72 | public RecognitionResult(String inFoundCommand, float inScore, boolean inIsNewCommand) { 73 | foundCommand = inFoundCommand; 74 | score = inScore; 75 | isNewCommand = inIsNewCommand; 76 | } 77 | } 78 | 79 | private static class ScoreForSorting implements Comparable { 80 | public final float score; 81 | public final int index; 82 | 83 | public ScoreForSorting(float inScore, int inIndex) { 84 | score = inScore; 85 | index = inIndex; 86 | } 87 | 88 | @Override 89 | public int compareTo(ScoreForSorting other) { 90 | if (this.score > other.score) { 91 | return -1; 92 | } else if (this.score < other.score) { 93 | return 1; 94 | } else { 95 | return 0; 96 | } 97 | } 98 | } 99 | 100 | public RecognitionResult processLatestResults(float[] currentResults, long currentTimeMS) { 101 | if (currentResults.length != labelsCount) { 102 | throw new RuntimeException( 103 | "The results for recognition should contain " 104 | + labelsCount 105 | + " elements, but there are " 106 | + currentResults.length); 107 | } 108 | 109 | if ((!previousResults.isEmpty()) && (currentTimeMS < previousResults.getFirst().first)) { 110 | throw new RuntimeException( 111 | "You must feed results in increasing time order, but received a timestamp of " 112 | + currentTimeMS 113 | + " that was earlier than the previous one of " 114 | + previousResults.getFirst().first); 115 | } 116 | 117 | final int howManyResults = previousResults.size(); 118 | // Ignore any results that are coming in too frequently. 119 | if (howManyResults > 1) { 120 | final long timeSinceMostRecent = currentTimeMS - previousResults.getLast().first; 121 | if (timeSinceMostRecent < minimumTimeBetweenSamplesMs) { 122 | return new RecognitionResult(previousTopLabel, previousTopLabelScore, false); 123 | } 124 | } 125 | 126 | // Add the latest results to the head of the queue. 127 | previousResults.addLast(new Pair(currentTimeMS, currentResults)); 128 | 129 | // Prune any earlier results that are too old for the averaging window. 130 | final long timeLimit = currentTimeMS - averageWindowDurationMs; 131 | while (previousResults.getFirst().first < timeLimit) { 132 | previousResults.removeFirst(); 133 | } 134 | 135 | // If there are too few results, assume the result will be unreliable and 136 | // bail. 137 | final long earliestTime = previousResults.getFirst().first; 138 | final long samplesDuration = currentTimeMS - earliestTime; 139 | if ((howManyResults < minimumCount) 140 | || (samplesDuration < (averageWindowDurationMs / MINIMUM_TIME_FRACTION))) { 141 | Log.v("RecognizeResult", "Too few results"); 142 | return new RecognitionResult(previousTopLabel, 0.0f, false); 143 | } 144 | 145 | // Calculate the average score across all the results in the window. 146 | float[] averageScores = new float[labelsCount]; 147 | for (Pair previousResult : previousResults) { 148 | final float[] scoresTensor = previousResult.second; 149 | int i = 0; 150 | while (i < scoresTensor.length) { 151 | averageScores[i] += scoresTensor[i] / howManyResults; 152 | ++i; 153 | } 154 | } 155 | 156 | // Sort the averaged results in descending score order. 157 | ScoreForSorting[] sortedAverageScores = new ScoreForSorting[labelsCount]; 158 | for (int i = 0; i < labelsCount; ++i) { 159 | sortedAverageScores[i] = new ScoreForSorting(averageScores[i], i); 160 | } 161 | Arrays.sort(sortedAverageScores); 162 | 163 | // See if the latest top score is enough to trigger a detection. 164 | final int currentTopIndex = sortedAverageScores[0].index; 165 | final String currentTopLabel = labels.get(currentTopIndex); 166 | final float currentTopScore = sortedAverageScores[0].score; 167 | // If we've recently had another label trigger, assume one that occurs too 168 | // soon afterwards is a bad result. 169 | long timeSinceLastTop; 170 | if (previousTopLabel.equals(SILENCE_LABEL) || (previousTopLabelTime == Long.MIN_VALUE)) { 171 | timeSinceLastTop = Long.MAX_VALUE; 172 | } else { 173 | timeSinceLastTop = currentTimeMS - previousTopLabelTime; 174 | } 175 | boolean isNewCommand; 176 | if ((currentTopScore > detectionThreshold) && (timeSinceLastTop > suppressionMs)) { 177 | previousTopLabel = currentTopLabel; 178 | previousTopLabelTime = currentTimeMS; 179 | previousTopLabelScore = currentTopScore; 180 | isNewCommand = true; 181 | } else { 182 | isNewCommand = false; 183 | } 184 | return new RecognitionResult(currentTopLabel, currentTopScore, isNewCommand); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/ResultsView.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package org.tensorflow.demo; 17 | 18 | import java.util.List; 19 | import org.tensorflow.demo.Classifier.Recognition; 20 | 21 | public interface ResultsView { 22 | public void setResults(final List results); 23 | public void setDuration(final long duration); 24 | } 25 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/TFLiteImageClassifier.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package org.tensorflow.demo; 17 | 18 | import android.content.res.AssetFileDescriptor; 19 | import android.content.res.AssetManager; 20 | import android.graphics.Bitmap; 21 | import android.os.SystemClock; 22 | import android.os.Trace; 23 | import android.util.Log; 24 | import java.io.BufferedReader; 25 | import java.io.FileInputStream; 26 | import java.io.IOException; 27 | import java.io.InputStreamReader; 28 | import java.nio.ByteBuffer; 29 | import java.nio.ByteOrder; 30 | import java.nio.MappedByteBuffer; 31 | import java.nio.channels.FileChannel; 32 | import java.util.ArrayList; 33 | import java.util.Comparator; 34 | import java.util.List; 35 | import java.util.PriorityQueue; 36 | import java.util.Vector; 37 | import org.tensorflow.lite.Interpreter; 38 | 39 | /** A classifier specialized to label images using TensorFlow. */ 40 | public class TFLiteImageClassifier implements Classifier { 41 | private static final String TAG = "TFLiteImageClassifier"; 42 | 43 | // Only return this many results with at least this confidence. 44 | private static final int MAX_RESULTS = 3; 45 | 46 | private Interpreter tfLite; 47 | 48 | /** Dimensions of inputs. */ 49 | private static final int DIM_BATCH_SIZE = 1; 50 | 51 | private static final int DIM_PIXEL_SIZE = 3; 52 | 53 | private static final int DIM_IMG_SIZE_X = 224; 54 | private static final int DIM_IMG_SIZE_Y = 224; 55 | 56 | byte[][] labelProb; 57 | 58 | // Pre-allocated buffers. 59 | private Vector labels = new Vector(); 60 | private int[] intValues; 61 | private ByteBuffer imgData = null; 62 | 63 | private TFLiteImageClassifier() {} 64 | 65 | /** Memory-map the model file in Assets. */ 66 | private static MappedByteBuffer loadModelFile(AssetManager assets, String modelFilename) 67 | throws IOException { 68 | AssetFileDescriptor fileDescriptor = assets.openFd(modelFilename); 69 | FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor()); 70 | FileChannel fileChannel = inputStream.getChannel(); 71 | long startOffset = fileDescriptor.getStartOffset(); 72 | long declaredLength = fileDescriptor.getDeclaredLength(); 73 | return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength); 74 | } 75 | 76 | /** 77 | * Initializes a native TensorFlow session for classifying images. 78 | * 79 | * @param assetManager The asset manager to be used to load assets. 80 | * @param modelFilename The filepath of the model GraphDef protocol buffer. 81 | * @param labelFilename The filepath of label file for classes. 82 | * @param inputSize The input size. A square image of inputSize x inputSize is assumed. 83 | * @throws IOException 84 | */ 85 | public static Classifier create( 86 | AssetManager assetManager, String modelFilename, String labelFilename, int inputSize) { 87 | TFLiteImageClassifier c = new TFLiteImageClassifier(); 88 | 89 | // Read the label names into memory. 90 | // TODO(andrewharp): make this handle non-assets. 91 | Log.i(TAG, "Reading labels from: " + labelFilename); 92 | BufferedReader br = null; 93 | try { 94 | br = new BufferedReader(new InputStreamReader(assetManager.open(labelFilename))); 95 | String line; 96 | while ((line = br.readLine()) != null) { 97 | c.labels.add(line); 98 | } 99 | br.close(); 100 | } catch (IOException e) { 101 | throw new RuntimeException("Problem reading label file!" , e); 102 | } 103 | 104 | c.imgData = 105 | ByteBuffer.allocateDirect( 106 | DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * DIM_PIXEL_SIZE); 107 | 108 | c.imgData.order(ByteOrder.nativeOrder()); 109 | try { 110 | c.tfLite = new Interpreter(loadModelFile(assetManager, modelFilename)); 111 | } catch (Exception e) { 112 | throw new RuntimeException(e); 113 | } 114 | 115 | // The shape of the output is [N, NUM_CLASSES], where N is the batch size. 116 | Log.i(TAG, "Read " + c.labels.size() + " labels"); 117 | 118 | // Pre-allocate buffers. 119 | c.intValues = new int[inputSize * inputSize]; 120 | 121 | c.labelProb = new byte[1][c.labels.size()]; 122 | 123 | return c; 124 | } 125 | 126 | /** Writes Image data into a {@code ByteBuffer}. */ 127 | private void convertBitmapToByteBuffer(Bitmap bitmap) { 128 | if (imgData == null) { 129 | return; 130 | } 131 | imgData.rewind(); 132 | bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight()); 133 | // Convert the image to floating point. 134 | int pixel = 0; 135 | long startTime = SystemClock.uptimeMillis(); 136 | for (int i = 0; i < DIM_IMG_SIZE_X; ++i) { 137 | for (int j = 0; j < DIM_IMG_SIZE_Y; ++j) { 138 | final int val = intValues[pixel++]; 139 | imgData.put((byte) ((val >> 16) & 0xFF)); 140 | imgData.put((byte) ((val >> 8) & 0xFF)); 141 | imgData.put((byte) (val & 0xFF)); 142 | } 143 | } 144 | long endTime = SystemClock.uptimeMillis(); 145 | Log.d(TAG, "Timecost to put values into ByteBuffer: " + Long.toString(endTime - startTime)); 146 | } 147 | 148 | @Override 149 | public List recognizeImage(final Bitmap bitmap) { 150 | // Log this method so that it can be analyzed with systrace. 151 | Trace.beginSection("recognizeImage"); 152 | 153 | Trace.beginSection("preprocessBitmap"); 154 | 155 | long startTime; 156 | long endTime; 157 | startTime = SystemClock.uptimeMillis(); 158 | 159 | convertBitmapToByteBuffer(bitmap); 160 | 161 | // Run the inference call. 162 | Trace.beginSection("run"); 163 | startTime = SystemClock.uptimeMillis(); 164 | tfLite.run(imgData, labelProb); 165 | endTime = SystemClock.uptimeMillis(); 166 | Log.i(TAG, "Inf time: " + (endTime - startTime)); 167 | Trace.endSection(); 168 | 169 | // Find the best classifications. 170 | PriorityQueue pq = 171 | new PriorityQueue( 172 | 3, 173 | new Comparator() { 174 | @Override 175 | public int compare(Recognition lhs, Recognition rhs) { 176 | // Intentionally reversed to put high confidence at the head of the queue. 177 | return Float.compare(rhs.getConfidence(), lhs.getConfidence()); 178 | } 179 | }); 180 | for (int i = 0; i < labels.size(); ++i) { 181 | pq.add( 182 | new Recognition( 183 | "" + i, 184 | labels.size() > i ? labels.get(i) : "unknown", 185 | (float) labelProb[0][i], 186 | null)); 187 | } 188 | final ArrayList recognitions = new ArrayList(); 189 | int recognitionsSize = Math.min(pq.size(), MAX_RESULTS); 190 | for (int i = 0; i < recognitionsSize; ++i) { 191 | recognitions.add(pq.poll()); 192 | } 193 | Trace.endSection(); // "recognizeImage" 194 | return recognitions; 195 | } 196 | 197 | @Override 198 | public void enableStatLogging(boolean logStats) { 199 | } 200 | 201 | @Override 202 | public String getStatString() { 203 | return ""; 204 | } 205 | 206 | @Override 207 | public void close() { 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/TFLiteObjectDetectionAPIModel.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package org.tensorflow.demo; 17 | 18 | import android.content.res.AssetFileDescriptor; 19 | import android.content.res.AssetManager; 20 | import android.graphics.Bitmap; 21 | import android.graphics.RectF; 22 | import android.os.Trace; 23 | import java.io.BufferedReader; 24 | import java.io.FileInputStream; 25 | import java.io.IOException; 26 | import java.io.InputStream; 27 | import java.io.InputStreamReader; 28 | import java.nio.ByteBuffer; 29 | import java.nio.ByteOrder; 30 | import java.nio.MappedByteBuffer; 31 | import java.nio.channels.FileChannel; 32 | import java.util.ArrayList; 33 | import java.util.HashMap; 34 | import java.util.List; 35 | import java.util.Map; 36 | import java.util.Vector; 37 | import org.tensorflow.demo.env.Logger; 38 | import org.tensorflow.lite.Interpreter; 39 | 40 | /** 41 | * Wrapper for frozen detection models trained using the Tensorflow Object Detection API: 42 | * github.com/tensorflow/models/tree/master/research/object_detection 43 | */ 44 | public class TFLiteObjectDetectionAPIModel implements Classifier { 45 | private static final Logger LOGGER = new Logger(); 46 | 47 | // Only return this many results. 48 | private static final int NUM_DETECTIONS = 10; 49 | private boolean isModelQuantized; 50 | // Float model 51 | private static final float IMAGE_MEAN = 128.0f; 52 | private static final float IMAGE_STD = 128.0f; 53 | // Number of threads in the java app 54 | private static final int NUM_THREADS = 4; 55 | // Config values. 56 | private int inputSize; 57 | // Pre-allocated buffers. 58 | private Vector labels = new Vector(); 59 | private int[] intValues; 60 | // outputLocations: array of shape [Batchsize, NUM_DETECTIONS,4] 61 | // contains the location of detected boxes 62 | private float[][][] outputLocations; 63 | // outputClasses: array of shape [Batchsize, NUM_DETECTIONS] 64 | // contains the classes of detected boxes 65 | private float[][] outputClasses; 66 | // outputScores: array of shape [Batchsize, NUM_DETECTIONS] 67 | // contains the scores of detected boxes 68 | private float[][] outputScores; 69 | // numDetections: array of shape [Batchsize] 70 | // contains the number of detected boxes 71 | private float[] numDetections; 72 | 73 | private ByteBuffer imgData; 74 | 75 | private Interpreter tfLite; 76 | 77 | 78 | /** Memory-map the model file in Assets. */ 79 | private static MappedByteBuffer loadModelFile(AssetManager assets, String modelFilename) 80 | throws IOException { 81 | AssetFileDescriptor fileDescriptor = assets.openFd(modelFilename); 82 | FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor()); 83 | FileChannel fileChannel = inputStream.getChannel(); 84 | long startOffset = fileDescriptor.getStartOffset(); 85 | long declaredLength = fileDescriptor.getDeclaredLength(); 86 | return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength); 87 | } 88 | 89 | /** 90 | * Initializes a native TensorFlow session for classifying images. 91 | * 92 | * @param assetManager The asset manager to be used to load assets. 93 | * @param modelFilename The filepath of the model GraphDef protocol buffer. 94 | * @param labelFilename The filepath of label file for classes. 95 | * @param inputSize The size of image input 96 | * @param isQuantized Boolean representing model is quantized or not 97 | */ 98 | public static Classifier create( 99 | final AssetManager assetManager, 100 | final String modelFilename, 101 | final String labelFilename, 102 | final int inputSize, 103 | final boolean isQuantized) 104 | throws IOException { 105 | final TFLiteObjectDetectionAPIModel d = new TFLiteObjectDetectionAPIModel(); 106 | 107 | InputStream labelsInput = null; 108 | String actualFilename = labelFilename.split("file:///android_asset/")[1]; 109 | labelsInput = assetManager.open(actualFilename); 110 | BufferedReader br = null; 111 | br = new BufferedReader(new InputStreamReader(labelsInput)); 112 | String line; 113 | while ((line = br.readLine()) != null) { 114 | LOGGER.w(line); 115 | d.labels.add(line); 116 | } 117 | br.close(); 118 | 119 | d.inputSize = inputSize; 120 | 121 | try { 122 | d.tfLite = new Interpreter(loadModelFile(assetManager, modelFilename)); 123 | } catch (Exception e) { 124 | throw new RuntimeException(e); 125 | } 126 | 127 | d.isModelQuantized = isQuantized; 128 | // Pre-allocate buffers. 129 | int numBytesPerChannel; 130 | if (isQuantized) { 131 | numBytesPerChannel = 1; // Quantized 132 | } else { 133 | numBytesPerChannel = 4; // Floating point 134 | } 135 | d.imgData = ByteBuffer.allocateDirect(1 * d.inputSize * d.inputSize * 3 * numBytesPerChannel); 136 | d.imgData.order(ByteOrder.nativeOrder()); 137 | d.intValues = new int[d.inputSize * d.inputSize]; 138 | 139 | d.tfLite.setNumThreads(NUM_THREADS); 140 | d.outputLocations = new float[1][NUM_DETECTIONS][4]; 141 | d.outputClasses = new float[1][NUM_DETECTIONS]; 142 | d.outputScores = new float[1][NUM_DETECTIONS]; 143 | d.numDetections = new float[1]; 144 | return d; 145 | } 146 | 147 | private TFLiteObjectDetectionAPIModel() {} 148 | 149 | @Override 150 | public List recognizeImage(final Bitmap bitmap) { 151 | // Log this method so that it can be analyzed with systrace. 152 | Trace.beginSection("recognizeImage"); 153 | 154 | Trace.beginSection("preprocessBitmap"); 155 | // Preprocess the image data from 0-255 int to normalized float based 156 | // on the provided parameters. 157 | bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight()); 158 | 159 | imgData.rewind(); 160 | for (int i = 0; i < inputSize; ++i) { 161 | for (int j = 0; j < inputSize; ++j) { 162 | int pixelValue = intValues[i * inputSize + j]; 163 | if (isModelQuantized) { 164 | // Quantized model 165 | imgData.put((byte) ((pixelValue >> 16) & 0xFF)); 166 | imgData.put((byte) ((pixelValue >> 8) & 0xFF)); 167 | imgData.put((byte) (pixelValue & 0xFF)); 168 | } else { // Float model 169 | imgData.putFloat((((pixelValue >> 16) & 0xFF) - IMAGE_MEAN) / IMAGE_STD); 170 | imgData.putFloat((((pixelValue >> 8) & 0xFF) - IMAGE_MEAN) / IMAGE_STD); 171 | imgData.putFloat(((pixelValue & 0xFF) - IMAGE_MEAN) / IMAGE_STD); 172 | } 173 | } 174 | } 175 | Trace.endSection(); // preprocessBitmap 176 | 177 | // Copy the input data into TensorFlow. 178 | Trace.beginSection("feed"); 179 | outputLocations = new float[1][NUM_DETECTIONS][4]; 180 | outputClasses = new float[1][NUM_DETECTIONS]; 181 | outputScores = new float[1][NUM_DETECTIONS]; 182 | numDetections = new float[1]; 183 | 184 | Object[] inputArray = {imgData}; 185 | Map outputMap = new HashMap<>(); 186 | outputMap.put(0, outputLocations); 187 | outputMap.put(1, outputClasses); 188 | outputMap.put(2, outputScores); 189 | outputMap.put(3, numDetections); 190 | Trace.endSection(); 191 | 192 | // Run the inference call. 193 | Trace.beginSection("run"); 194 | tfLite.runForMultipleInputsOutputs(inputArray, outputMap); 195 | Trace.endSection(); 196 | 197 | // Show the best detections. 198 | // after scaling them back to the input size. 199 | final ArrayList recognitions = new ArrayList<>(NUM_DETECTIONS); 200 | for (int i = 0; i < NUM_DETECTIONS; ++i) { 201 | final RectF detection = 202 | new RectF( 203 | outputLocations[0][i][1] * inputSize, 204 | outputLocations[0][i][0] * inputSize, 205 | outputLocations[0][i][3] * inputSize, 206 | outputLocations[0][i][2] * inputSize); 207 | // SSD Mobilenet V1 Model assumes class 0 is background class 208 | // in label file and class labels start from 1 to number_of_classes+1, 209 | // while outputClasses correspond to class index from 0 to number_of_classes 210 | int labelOffset = 1; 211 | recognitions.add( 212 | new Recognition( 213 | "" + i, 214 | labels.get((int) outputClasses[0][i] + labelOffset), 215 | outputScores[0][i], 216 | detection)); 217 | } 218 | Trace.endSection(); // "recognizeImage" 219 | return recognitions; 220 | } 221 | 222 | @Override 223 | public void enableStatLogging(final boolean logStats) { 224 | } 225 | 226 | @Override 227 | public String getStatString() { 228 | return ""; 229 | } 230 | 231 | @Override 232 | public void close() { 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/env/AssetUtils.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2017 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package org.tensorflow.demo.env; 17 | 18 | import android.content.Context; 19 | import android.content.res.AssetManager; 20 | import android.util.Log; 21 | import java.io.File; 22 | import java.io.FileOutputStream; 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.io.OutputStream; 26 | 27 | /** Utilities for dealing with assets. */ 28 | public class AssetUtils { 29 | 30 | private static final String TAG = AssetUtils.class.getSimpleName(); 31 | 32 | private static final int BYTE_BUF_SIZE = 2048; 33 | 34 | /** 35 | * Copies a file from assets. 36 | * 37 | * @param context application context used to discover assets. 38 | * @param assetName the relative file name within assets. 39 | * @param targetName the target file name, always over write the existing file. 40 | * @throws IOException if operation fails. 41 | */ 42 | public static void copy(Context context, String assetName, String targetName) throws IOException { 43 | 44 | Log.d(TAG, "creating file " + targetName + " from " + assetName); 45 | 46 | File targetFile = null; 47 | InputStream inputStream = null; 48 | FileOutputStream outputStream = null; 49 | 50 | try { 51 | AssetManager assets = context.getAssets(); 52 | targetFile = new File(targetName); 53 | inputStream = assets.open(assetName); 54 | // TODO(kanlig): refactor log messages to make them more useful. 55 | Log.d(TAG, "Creating outputstream"); 56 | outputStream = new FileOutputStream(targetFile, false /* append */); 57 | copy(inputStream, outputStream); 58 | } finally { 59 | if (outputStream != null) { 60 | outputStream.close(); 61 | } 62 | if (inputStream != null) { 63 | inputStream.close(); 64 | } 65 | } 66 | } 67 | 68 | private static void copy(InputStream from, OutputStream to) throws IOException { 69 | byte[] buf = new byte[BYTE_BUF_SIZE]; 70 | while (true) { 71 | int r = from.read(buf); 72 | if (r == -1) { 73 | break; 74 | } 75 | to.write(buf, 0, r); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/env/BorderedText.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package org.tensorflow.demo.env; 17 | 18 | import android.graphics.Canvas; 19 | import android.graphics.Color; 20 | import android.graphics.Paint; 21 | import android.graphics.Paint.Align; 22 | import android.graphics.Paint.Style; 23 | import android.graphics.Rect; 24 | import android.graphics.Typeface; 25 | import java.util.Vector; 26 | 27 | /** 28 | * A class that encapsulates the tedious bits of rendering legible, bordered text onto a canvas. 29 | */ 30 | public class BorderedText { 31 | private final Paint interiorPaint; 32 | private final Paint exteriorPaint; 33 | 34 | private final float textSize; 35 | 36 | /** 37 | * Creates a left-aligned bordered text object with a white interior, and a black exterior with 38 | * the specified text size. 39 | * 40 | * @param textSize text size in pixels 41 | */ 42 | public BorderedText(final float textSize) { 43 | this(Color.WHITE, Color.BLACK, textSize); 44 | } 45 | 46 | /** 47 | * Create a bordered text object with the specified interior and exterior colors, text size and 48 | * alignment. 49 | * 50 | * @param interiorColor the interior text color 51 | * @param exteriorColor the exterior text color 52 | * @param textSize text size in pixels 53 | */ 54 | public BorderedText(final int interiorColor, final int exteriorColor, final float textSize) { 55 | interiorPaint = new Paint(); 56 | interiorPaint.setTextSize(textSize); 57 | interiorPaint.setColor(interiorColor); 58 | interiorPaint.setStyle(Style.FILL); 59 | interiorPaint.setAntiAlias(false); 60 | interiorPaint.setAlpha(255); 61 | 62 | exteriorPaint = new Paint(); 63 | exteriorPaint.setTextSize(textSize); 64 | exteriorPaint.setColor(exteriorColor); 65 | exteriorPaint.setStyle(Style.FILL_AND_STROKE); 66 | exteriorPaint.setStrokeWidth(textSize / 8); 67 | exteriorPaint.setAntiAlias(false); 68 | exteriorPaint.setAlpha(255); 69 | 70 | this.textSize = textSize; 71 | } 72 | 73 | public void setTypeface(Typeface typeface) { 74 | interiorPaint.setTypeface(typeface); 75 | exteriorPaint.setTypeface(typeface); 76 | } 77 | 78 | public void drawText(final Canvas canvas, final float posX, final float posY, final String text) { 79 | canvas.drawText(text, posX, posY, exteriorPaint); 80 | canvas.drawText(text, posX, posY, interiorPaint); 81 | } 82 | 83 | public void drawLines(Canvas canvas, final float posX, final float posY, Vector lines) { 84 | int lineNum = 0; 85 | for (final String line : lines) { 86 | drawText(canvas, posX, posY - getTextSize() * (lines.size() - lineNum - 1), line); 87 | ++lineNum; 88 | } 89 | } 90 | 91 | public void setInteriorColor(final int color) { 92 | interiorPaint.setColor(color); 93 | } 94 | 95 | public void setExteriorColor(final int color) { 96 | exteriorPaint.setColor(color); 97 | } 98 | 99 | public float getTextSize() { 100 | return textSize; 101 | } 102 | 103 | public void setAlpha(final int alpha) { 104 | interiorPaint.setAlpha(alpha); 105 | exteriorPaint.setAlpha(alpha); 106 | } 107 | 108 | public void getTextBounds( 109 | final String line, final int index, final int count, final Rect lineBounds) { 110 | interiorPaint.getTextBounds(line, index, count, lineBounds); 111 | } 112 | 113 | public void setTextAlign(final Align align) { 114 | interiorPaint.setTextAlign(align); 115 | exteriorPaint.setTextAlign(align); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/env/Logger.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package org.tensorflow.demo.env; 17 | 18 | import android.util.Log; 19 | import java.util.HashSet; 20 | import java.util.Set; 21 | 22 | /** 23 | * Wrapper for the platform log function, allows convenient message prefixing and log disabling. 24 | */ 25 | public final class Logger { 26 | private static final String DEFAULT_TAG = "tensorflow"; 27 | private static final int DEFAULT_MIN_LOG_LEVEL = Log.DEBUG; 28 | 29 | // Classes to be ignored when examining the stack trace 30 | private static final Set IGNORED_CLASS_NAMES; 31 | 32 | static { 33 | IGNORED_CLASS_NAMES = new HashSet(3); 34 | IGNORED_CLASS_NAMES.add("dalvik.system.VMStack"); 35 | IGNORED_CLASS_NAMES.add("java.lang.Thread"); 36 | IGNORED_CLASS_NAMES.add(Logger.class.getCanonicalName()); 37 | } 38 | 39 | private final String tag; 40 | private final String messagePrefix; 41 | private int minLogLevel = DEFAULT_MIN_LOG_LEVEL; 42 | 43 | /** 44 | * Creates a Logger using the class name as the message prefix. 45 | * 46 | * @param clazz the simple name of this class is used as the message prefix. 47 | */ 48 | public Logger(final Class clazz) { 49 | this(clazz.getSimpleName()); 50 | } 51 | 52 | /** 53 | * Creates a Logger using the specified message prefix. 54 | * 55 | * @param messagePrefix is prepended to the text of every message. 56 | */ 57 | public Logger(final String messagePrefix) { 58 | this(DEFAULT_TAG, messagePrefix); 59 | } 60 | 61 | /** 62 | * Creates a Logger with a custom tag and a custom message prefix. If the message prefix 63 | * is set to
null
, the caller's class name is used as the prefix. 64 | * 65 | * @param tag identifies the source of a log message. 66 | * @param messagePrefix prepended to every message if non-null. If null, the name of the caller is 67 | * being used 68 | */ 69 | public Logger(final String tag, final String messagePrefix) { 70 | this.tag = tag; 71 | final String prefix = messagePrefix == null ? getCallerSimpleName() : messagePrefix; 72 | this.messagePrefix = (prefix.length() > 0) ? prefix + ": " : prefix; 73 | } 74 | 75 | /** 76 | * Creates a Logger using the caller's class name as the message prefix. 77 | */ 78 | public Logger() { 79 | this(DEFAULT_TAG, null); 80 | } 81 | 82 | /** 83 | * Creates a Logger using the caller's class name as the message prefix. 84 | */ 85 | public Logger(final int minLogLevel) { 86 | this(DEFAULT_TAG, null); 87 | this.minLogLevel = minLogLevel; 88 | } 89 | 90 | public void setMinLogLevel(final int minLogLevel) { 91 | this.minLogLevel = minLogLevel; 92 | } 93 | 94 | public boolean isLoggable(final int logLevel) { 95 | return logLevel >= minLogLevel || Log.isLoggable(tag, logLevel); 96 | } 97 | 98 | /** 99 | * Return caller's simple name. 100 | * 101 | * Android getStackTrace() returns an array that looks like this: 102 | * stackTrace[0]: dalvik.system.VMStack 103 | * stackTrace[1]: java.lang.Thread 104 | * stackTrace[2]: com.google.android.apps.unveil.env.UnveilLogger 105 | * stackTrace[3]: com.google.android.apps.unveil.BaseApplication 106 | * 107 | * This function returns the simple version of the first non-filtered name. 108 | * 109 | * @return caller's simple name 110 | */ 111 | private static String getCallerSimpleName() { 112 | // Get the current callstack so we can pull the class of the caller off of it. 113 | final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); 114 | 115 | for (final StackTraceElement elem : stackTrace) { 116 | final String className = elem.getClassName(); 117 | if (!IGNORED_CLASS_NAMES.contains(className)) { 118 | // We're only interested in the simple name of the class, not the complete package. 119 | final String[] classParts = className.split("\\."); 120 | return classParts[classParts.length - 1]; 121 | } 122 | } 123 | 124 | return Logger.class.getSimpleName(); 125 | } 126 | 127 | private String toMessage(final String format, final Object... args) { 128 | return messagePrefix + (args.length > 0 ? String.format(format, args) : format); 129 | } 130 | 131 | public void v(final String format, final Object... args) { 132 | if (isLoggable(Log.VERBOSE)) { 133 | Log.v(tag, toMessage(format, args)); 134 | } 135 | } 136 | 137 | public void v(final Throwable t, final String format, final Object... args) { 138 | if (isLoggable(Log.VERBOSE)) { 139 | Log.v(tag, toMessage(format, args), t); 140 | } 141 | } 142 | 143 | public void d(final String format, final Object... args) { 144 | if (isLoggable(Log.DEBUG)) { 145 | Log.d(tag, toMessage(format, args)); 146 | } 147 | } 148 | 149 | public void d(final Throwable t, final String format, final Object... args) { 150 | if (isLoggable(Log.DEBUG)) { 151 | Log.d(tag, toMessage(format, args), t); 152 | } 153 | } 154 | 155 | public void i(final String format, final Object... args) { 156 | if (isLoggable(Log.INFO)) { 157 | Log.i(tag, toMessage(format, args)); 158 | } 159 | } 160 | 161 | public void i(final Throwable t, final String format, final Object... args) { 162 | if (isLoggable(Log.INFO)) { 163 | Log.i(tag, toMessage(format, args), t); 164 | } 165 | } 166 | 167 | public void w(final String format, final Object... args) { 168 | if (isLoggable(Log.WARN)) { 169 | Log.w(tag, toMessage(format, args)); 170 | } 171 | } 172 | 173 | public void w(final Throwable t, final String format, final Object... args) { 174 | if (isLoggable(Log.WARN)) { 175 | Log.w(tag, toMessage(format, args), t); 176 | } 177 | } 178 | 179 | public void e(final String format, final Object... args) { 180 | if (isLoggable(Log.ERROR)) { 181 | Log.e(tag, toMessage(format, args)); 182 | } 183 | } 184 | 185 | public void e(final Throwable t, final String format, final Object... args) { 186 | if (isLoggable(Log.ERROR)) { 187 | Log.e(tag, toMessage(format, args), t); 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/env/Size.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package org.tensorflow.demo.env; 17 | 18 | import android.graphics.Bitmap; 19 | import android.text.TextUtils; 20 | import java.io.Serializable; 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | /** 25 | * Size class independent of a Camera object. 26 | */ 27 | public class Size implements Comparable, Serializable { 28 | 29 | // 1.4 went out with this UID so we'll need to maintain it to preserve pending queries when 30 | // upgrading. 31 | public static final long serialVersionUID = 7689808733290872361L; 32 | 33 | public final int width; 34 | public final int height; 35 | 36 | public Size(final int width, final int height) { 37 | this.width = width; 38 | this.height = height; 39 | } 40 | 41 | public Size(final Bitmap bmp) { 42 | this.width = bmp.getWidth(); 43 | this.height = bmp.getHeight(); 44 | } 45 | 46 | /** 47 | * Rotate a size by the given number of degrees. 48 | * @param size Size to rotate. 49 | * @param rotation Degrees {0, 90, 180, 270} to rotate the size. 50 | * @return Rotated size. 51 | */ 52 | public static Size getRotatedSize(final Size size, final int rotation) { 53 | if (rotation % 180 != 0) { 54 | // The phone is portrait, therefore the camera is sideways and frame should be rotated. 55 | return new Size(size.height, size.width); 56 | } 57 | return size; 58 | } 59 | 60 | public static Size parseFromString(String sizeString) { 61 | if (TextUtils.isEmpty(sizeString)) { 62 | return null; 63 | } 64 | 65 | sizeString = sizeString.trim(); 66 | 67 | // The expected format is "x". 68 | final String[] components = sizeString.split("x"); 69 | if (components.length == 2) { 70 | try { 71 | final int width = Integer.parseInt(components[0]); 72 | final int height = Integer.parseInt(components[1]); 73 | return new Size(width, height); 74 | } catch (final NumberFormatException e) { 75 | return null; 76 | } 77 | } else { 78 | return null; 79 | } 80 | } 81 | 82 | public static List sizeStringToList(final String sizes) { 83 | final List sizeList = new ArrayList(); 84 | if (sizes != null) { 85 | final String[] pairs = sizes.split(","); 86 | for (final String pair : pairs) { 87 | final Size size = Size.parseFromString(pair); 88 | if (size != null) { 89 | sizeList.add(size); 90 | } 91 | } 92 | } 93 | return sizeList; 94 | } 95 | 96 | public static String sizeListToString(final List sizes) { 97 | String sizesString = ""; 98 | if (sizes != null && sizes.size() > 0) { 99 | sizesString = sizes.get(0).toString(); 100 | for (int i = 1; i < sizes.size(); i++) { 101 | sizesString += "," + sizes.get(i).toString(); 102 | } 103 | } 104 | return sizesString; 105 | } 106 | 107 | public final float aspectRatio() { 108 | return (float) width / (float) height; 109 | } 110 | 111 | @Override 112 | public int compareTo(final Size other) { 113 | return width * height - other.width * other.height; 114 | } 115 | 116 | @Override 117 | public boolean equals(final Object other) { 118 | if (other == null) { 119 | return false; 120 | } 121 | 122 | if (!(other instanceof Size)) { 123 | return false; 124 | } 125 | 126 | final Size otherSize = (Size) other; 127 | return (width == otherSize.width && height == otherSize.height); 128 | } 129 | 130 | @Override 131 | public int hashCode() { 132 | return width * 32713 + height; 133 | } 134 | 135 | @Override 136 | public String toString() { 137 | return dimensionsAsString(width, height); 138 | } 139 | 140 | public static final String dimensionsAsString(final int width, final int height) { 141 | return width + "x" + height; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/java/org/tensorflow/demo/env/SplitTimer.java: -------------------------------------------------------------------------------- 1 | /* Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | package org.tensorflow.demo.env; 17 | 18 | import android.os.SystemClock; 19 | 20 | /** 21 | * A simple utility timer for measuring CPU time and wall-clock splits. 22 | */ 23 | public class SplitTimer { 24 | private final Logger logger; 25 | 26 | private long lastWallTime; 27 | private long lastCpuTime; 28 | 29 | public SplitTimer(final String name) { 30 | logger = new Logger(name); 31 | newSplit(); 32 | } 33 | 34 | public void newSplit() { 35 | lastWallTime = SystemClock.uptimeMillis(); 36 | lastCpuTime = SystemClock.currentThreadTimeMillis(); 37 | } 38 | 39 | public void endSplit(final String splitName) { 40 | final long currWallTime = SystemClock.uptimeMillis(); 41 | final long currCpuTime = SystemClock.currentThreadTimeMillis(); 42 | 43 | logger.i( 44 | "%s: cpu=%dms wall=%dms", 45 | splitName, currCpuTime - lastCpuTime, currWallTime - lastWallTime); 46 | 47 | lastWallTime = currWallTime; 48 | lastCpuTime = currCpuTime; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/jnilibs/arm64-v8a/libtensorflow_demo.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TfLiteCameraDemo/app/src/main/jnilibs/arm64-v8a/libtensorflow_demo.so -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/jnilibs/arm64-v8a/libtensorflowlite_jni.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TfLiteCameraDemo/app/src/main/jnilibs/arm64-v8a/libtensorflowlite_jni.so -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/animator/color_animation.xml: -------------------------------------------------------------------------------- 1 | 16 | 18 | 24 | 30 | 31 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/drawable-hdpi/ic_action_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TfLiteCameraDemo/app/src/main/res/drawable-hdpi/ic_action_info.png -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TfLiteCameraDemo/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/drawable-hdpi/tile.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TfLiteCameraDemo/app/src/main/res/drawable-hdpi/tile.9.png -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/drawable-mdpi/ic_action_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TfLiteCameraDemo/app/src/main/res/drawable-mdpi/ic_action_info.png -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TfLiteCameraDemo/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/drawable-xhdpi/ic_action_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TfLiteCameraDemo/app/src/main/res/drawable-xhdpi/ic_action_info.png -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TfLiteCameraDemo/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/drawable-xxhdpi/ic_action_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TfLiteCameraDemo/app/src/main/res/drawable-xxhdpi/ic_action_info.png -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinatp/Tensorflow_Lite_Demo/e675b8da540b4d2f5db65342fe59225973f48940/TfLiteCameraDemo/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/drawable/border.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/layout/activity_camera.xml: -------------------------------------------------------------------------------- 1 | 16 | 23 | -------------------------------------------------------------------------------- /TfLiteCameraDemo/app/src/main/res/layout/activity_speech.xml: -------------------------------------------------------------------------------- 1 | 16 | 23 | 24 | 35 | 36 | 45 | 46 |