diff --git a/examples/demo-apps/android/ExecuTorchDemo/.gitignore b/examples/demo-apps/android/ExecuTorchDemo/.gitignore deleted file mode 100644 index e7bee2e2b1c..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -*.iml -.gradle -/local.properties -.idea -.DS_Store -/build -/captures -.externalNativeBuild -.cxx -local.properties -*.so diff --git a/examples/demo-apps/android/ExecuTorchDemo/README.md b/examples/demo-apps/android/ExecuTorchDemo/README.md deleted file mode 100644 index c6ee756458f..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/README.md +++ /dev/null @@ -1,132 +0,0 @@ -# Building an ExecuTorch Android Demo App - -This is forked from [PyTorch Android Demo App](https://github.com/pytorch/android-demo-app). - -This guide explains how to setup ExecuTorch for Android using a demo app. The app employs a [DeepLab v3](https://pytorch.org/hub/pytorch_vision_deeplabv3_resnet101/) model for image segmentation tasks. Models are exported to ExecuTorch using [XNNPACK FP32 backend](tutorial-xnnpack-delegate-lowering.md). - -::::{grid} 2 -:::{grid-item-card} What you will learn -:class-card: card-prerequisites -* How to set up a build target for Android arm64-v8a -* How to build the required ExecuTorch runtime with JNI wrapper for Android -* How to build the app with required JNI library and model file -::: - -:::{grid-item-card} Prerequisites -:class-card: card-prerequisites -* Refer to [Setting up ExecuTorch](https://pytorch.org/executorch/stable/getting-started-setup) to set up the repo and dev environment. -* Download and install [Android Studio and SDK](https://developer.android.com/studio). -* Supported Host OS: CentOS, macOS Ventura (M1/x86_64). See below for Qualcomm HTP specific requirements. -* *Qualcomm HTP Only[^1]:* To build and run on Qualcomm's AI Engine Direct, please follow [Building and Running ExecuTorch with Qualcomm AI Engine Direct Backend](backends-qualcomm.md) for hardware and software pre-requisites. The version we use for this tutorial is 2.19. The chip we use for this tutorial is SM8450. -::: -:::: - -[^1]: This section applies only if Qualcomm HTP Backend is needed in the app. Same applies to sections with title`Qualcomm Hexagon NPU`. - -```{note} -This demo app and tutorial has only been validated with arm64-v8a [ABI](https://developer.android.com/ndk/guides/abis). -``` - - -## Build - -### Ahead-Of-Time - -We generate the model file for the ExecuTorch runtime in Android Demo App. - -#### XNNPACK Delegation - -For delegating DeepLab v3 to XNNPACK backend, please do the following to export the model: - -```bash -cd executorch # go to executorch root -python3 -m examples.xnnpack.aot_compiler --model_name="dl3" --delegate -``` - -Then push the pte file to Android device: - -```bash -adb push dl3_xnnpack_fp32.pte /data/local/tmp/dl3_xnnpack_fp32.pte -``` - -For more detailed tutorial of lowering to XNNPACK, please see [XNNPACK backend](backends-xnnpack.md). - -#### Qualcomm Hexagon NPU - -For delegating to Qualcomm Hexagon NPU, please follow the tutorial [here](backends-qualcomm.md). - -```bash -python -m examples.qualcomm.scripts.deeplab_v3 -b build-android -m SM8450 -s -``` - -Then push the pte file to Android device: - -```bash -adb push deeplab_v3/dlv3_qnn.pte /data/local/tmp/dlv3_qnn.pte -``` - -### Runtime - -We build the required ExecuTorch runtime library (AAR) to run the model. - -#### XNNPACK - -```bash -# go to ExecuTorch repo root -export ANDROID_NDK= -export ANDROID_ABIS=arm64-v8a - -# Run the following lines from the `executorch/` folder -./install_executorch.sh --clean - -# Create a new directory `app/libs` for the AAR to live -pushd examples/demo-apps/android/ExecuTorchDemo -mkdir -p app/libs -popd - -# Build the AAR. It will include XNNPACK backend by default. -export BUILD_AAR_DIR=$(realpath examples/demo-apps/android/ExecuTorchDemo/app/libs) -sh scripts/build_android_library.sh -``` - -#### Qualcomm Hexagon NPU - -```bash -# go to ExecuTorch repo root -export ANDROID_NDK= -export ANDROID_ABIS=arm64-v8a -export QNN_SDK_ROOT= - -# Run the following lines from the `executorch/` folder -./install_executorch.sh --clean - -# Create a new directory `app/libs` for the AAR to live -pushd examples/demo-apps/android/ExecuTorchDemo -mkdir -p app/libs -popd - -# Build the AAR. It will include XNNPACK backend by default. -export BUILD_AAR_DIR=$(realpath examples/demo-apps/android/ExecuTorchDemo/app/libs) -sh scripts/build_android_library.sh -``` - -This is very similar to XNNPACK setup, but users now needs to define `QNN_SDK_ROOT` so that -QNN backend is built into the AAR. - -## Running the App - -1. Open the project `examples/demo-apps/android/ExecuTorchDemo` with Android Studio. - -2. [Run](https://developer.android.com/studio/run) the app (^R). - -Android Studio View
- -On the phone or emulator, you can try running the model: -Android Demo
- -## Takeaways -Through this tutorial we've learnt how to build the ExecuTorch runtime library with XNNPACK (or Qualcomm HTP) backend, and expose it to JNI layer to build the Android app running segmentation model. - -## Reporting Issues - -If you encountered any bugs or issues following this tutorial please file a bug/issue here on [Github](https://github.com/pytorch/executorch/issues/new). diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/.gitignore b/examples/demo-apps/android/ExecuTorchDemo/app/.gitignore deleted file mode 100644 index 796b96d1c40..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/build.gradle.kts b/examples/demo-apps/android/ExecuTorchDemo/app/build.gradle.kts deleted file mode 100644 index ca06671f328..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/app/build.gradle.kts +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. - */ - -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - namespace = "com.example.executorchdemo" - compileSdk = 34 - - defaultConfig { - applicationId = "com.example.executorchdemo" - minSdk = 24 - targetSdk = 33 - versionCode = 1 - versionName = "1.0" - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - vectorDrawables { useSupportLibrary = true } - externalNativeBuild { cmake { cppFlags += "" } } - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - kotlinOptions { jvmTarget = "1.8" } - buildFeatures { compose = true } - composeOptions { kotlinCompilerExtensionVersion = "1.4.3" } - packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } } -} - -dependencies { - implementation("androidx.core:core-ktx:1.9.0") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") - implementation("androidx.activity:activity-compose:1.7.0") - implementation(platform("androidx.compose:compose-bom:2023.03.00")) - implementation("androidx.compose.ui:ui") - implementation("androidx.compose.ui:ui-graphics") - implementation("androidx.compose.ui:ui-tooling-preview") - implementation("androidx.compose.material3:material3") - implementation("androidx.appcompat:appcompat:1.6.1") - implementation("androidx.camera:camera-core:1.3.0-rc02") - implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha12") - implementation("com.facebook.soloader:soloader:0.10.5") - implementation("com.facebook.fbjni:fbjni:0.5.1") - implementation(files("libs/executorch.aar")) - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") - androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00")) - androidTestImplementation("androidx.compose.ui:ui-test-junit4") - debugImplementation("androidx.compose.ui:ui-tooling") - debugImplementation("androidx.compose.ui:ui-test-manifest") -} - -tasks.register("setup") { - doFirst { - exec { - commandLine("sh", "setup.sh") - workingDir("../") - } - } -} diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/proguard-rules.pro b/examples/demo-apps/android/ExecuTorchDemo/app/proguard-rules.pro deleted file mode 100644 index 481bb434814..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/app/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/AndroidManifest.xml b/examples/demo-apps/android/ExecuTorchDemo/app/src/main/AndroidManifest.xml deleted file mode 100644 index 8d71b156398..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/BUCK b/examples/demo-apps/android/ExecuTorchDemo/app/src/main/BUCK deleted file mode 100644 index 371c991ce88..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/BUCK +++ /dev/null @@ -1,65 +0,0 @@ -load("@fbsource//tools/build_defs:manifold.bzl", "manifold_get") -load("@fbsource//tools/build_defs/android:fb_android_binary.bzl", "fb_android_binary") -load("@fbsource//tools/build_defs/android:fb_android_library.bzl", "fb_android_library") -load("@fbsource//tools/build_defs/android:fb_android_resource.bzl", "fb_android_resource") - -manifold_get( - name = "dl3_xnnpack_fp32", - out = "dl3_xnnpack_fp32.pte", - api_key = "executorch-key", - artifact_path = "tree/models/benchmarking/executorch/dl3_xnnpack_fp32.pte", - bucket_name = "executorch", - sha1 = "3e7af1d8f5ec4acb6de156d361715e16e5f53783", - timeout_msec = 120000, -) - -fb_android_resource( - name = "app_res", - assets = "assets", - package = "com.example.executorchdemo", - res = "res", -) - -fb_android_resource( - name = "model_res", - assets = {"dl3_xnnpack_fp32.pte": ":dl3_xnnpack_fp32"}, - package = "com.example.executorchdemo", - res = "res", -) - -fb_android_library( - name = "app_lib", - srcs = [ - "java/com/example/executorchdemo/MainActivity.java", - "java/com/example/executorchdemo/TensorImageUtils.java", - ], - autoglob = False, - language = "JAVA", - deps = [ - ":app_res", - "//xplat/executorch/extension/android:executorch", - ], -) - -fb_android_binary( - name = "ExecuTorchDemo", - keystore = "//fbandroid/keystores:debug", - manifest = "AndroidManifest.xml", - manifest_entries = { - "min_sdk_version": 19, # Android supports 19 for minimum - "target_sdk_version": 34, - "version_code": "1", - "version_name": "1.0", - }, - package_type = "release", - skip_proguard = True, - deps = [ - ":app_lib", - ":app_res", - ":model_res", - "//third-party/java/androidx/appcompat/appcompat:appcompat", - "//third-party/java/androidx/constraintlayout/constraintlayout:constraintlayout", - "//xplat/executorch/extension/android:executorch", - "//xplat/executorch/extension/android/jni:executorch_jni_full", - ], -) diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/TARGETS b/examples/demo-apps/android/ExecuTorchDemo/app/src/main/TARGETS deleted file mode 100644 index 5c4f482b5ea..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/TARGETS +++ /dev/null @@ -1 +0,0 @@ -# This file needs to exist to avoid build system breakage, see https://fburl.com/workplace/jtdlgdmd diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/assets/corgi.jpeg b/examples/demo-apps/android/ExecuTorchDemo/app/src/main/assets/corgi.jpeg deleted file mode 100644 index b7cdd3bf73d..00000000000 Binary files a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/assets/corgi.jpeg and /dev/null differ diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/assets/deeplab.jpg b/examples/demo-apps/android/ExecuTorchDemo/app/src/main/assets/deeplab.jpg deleted file mode 100644 index e840b670002..00000000000 Binary files a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/assets/deeplab.jpg and /dev/null differ diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/assets/dog.jpg b/examples/demo-apps/android/ExecuTorchDemo/app/src/main/assets/dog.jpg deleted file mode 100644 index e20f0ccbc48..00000000000 Binary files a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/assets/dog.jpg and /dev/null differ diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/java/com/example/executorchdemo/MainActivity.java b/examples/demo-apps/android/ExecuTorchDemo/app/src/main/java/com/example/executorchdemo/MainActivity.java deleted file mode 100644 index 9ac800b49a3..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/java/com/example/executorchdemo/MainActivity.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.example.executorchdemo; - -import android.app.Activity; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.Bundle; -import android.os.SystemClock; -import android.system.ErrnoException; -import android.system.Os; -import android.util.Log; -import android.view.View; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.ProgressBar; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Objects; -import org.pytorch.executorch.EValue; -import org.pytorch.executorch.Module; -import org.pytorch.executorch.Tensor; - -public class MainActivity extends Activity implements Runnable { - private ImageView mImageView; - private Button mButtonXnnpack; - private Button mButtonHtp; - private ProgressBar mProgressBar; - private Bitmap mBitmap = null; - private Module mModule = null; - private String mImagename = "corgi.jpeg"; - - // see http://host.robots.ox.ac.uk:8080/pascal/VOC/voc2007/segexamples/index.html for the list of - // classes with indexes - private static final int CLASSNUM = 21; - private static final int DOG = 12; - private static final int PERSON = 15; - private static final int SHEEP = 17; - - public static String assetFilePath(Context context, String assetName) throws IOException { - File file = new File(context.getFilesDir(), assetName); - if (file.exists() && file.length() > 0) { - return file.getAbsolutePath(); - } - - try (InputStream is = context.getAssets().open(assetName)) { - try (OutputStream os = new FileOutputStream(file)) { - byte[] buffer = new byte[4 * 1024]; - int read; - while ((read = is.read(buffer)) != -1) { - os.write(buffer, 0, read); - } - os.flush(); - } - return file.getAbsolutePath(); - } - } - - private void populateImage() { - try { - mBitmap = BitmapFactory.decodeStream(getAssets().open(mImagename)); - mBitmap = Bitmap.createScaledBitmap(mBitmap, 224, 224, true); - mImageView.setImageBitmap(mBitmap); - } catch (IOException e) { - Log.e("ImageSegmentation", "Error reading assets", e); - finish(); - } - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - try { - Os.setenv("ADSP_LIBRARY_PATH", getApplicationInfo().nativeLibraryDir, true); - } catch (ErrnoException e) { - Log.e("ExecuTorchDemo", "Cannot set ADSP_LIBRARY_PATH", e); - finish(); - } - - try { - mBitmap = BitmapFactory.decodeStream(getAssets().open(mImagename), null, null); - mBitmap = Bitmap.createScaledBitmap(mBitmap, 224, 224, true); - } catch (IOException e) { - Log.e("ImageSegmentation", "Error reading assets", e); - finish(); - } - - mModule = Module.load("/data/local/tmp/dl3_xnnpack_fp32.pte"); - - mImageView = findViewById(R.id.imageView); - mImageView.setImageBitmap(mBitmap); - - final Button buttonNext = findViewById(R.id.nextButton); - buttonNext.setOnClickListener( - new View.OnClickListener() { - public void onClick(View v) { - if (Objects.equals(mImagename, "corgi.jpeg")) { - mImagename = "dog.jpg"; - } else if (Objects.equals(mImagename, "dog.jpg")) { - mImagename = "deeplab.jpg"; - } else { - mImagename = "corgi.jpeg"; - } - populateImage(); - } - }); - - mButtonXnnpack = findViewById(R.id.xnnpackButton); - mButtonHtp = findViewById(R.id.htpButton); - mProgressBar = (ProgressBar) findViewById(R.id.progressBar); - mButtonXnnpack.setOnClickListener( - new View.OnClickListener() { - public void onClick(View v) { - mModule.destroy(); - mModule = Module.load("/data/local/tmp/dl3_xnnpack_fp32.pte"); - mButtonXnnpack.setEnabled(false); - mProgressBar.setVisibility(ProgressBar.VISIBLE); - mButtonXnnpack.setText(getString(R.string.run_model)); - - Thread thread = new Thread(MainActivity.this); - thread.start(); - } - }); - - mButtonHtp.setOnClickListener( - new View.OnClickListener() { - public void onClick(View v) { - mModule.destroy(); - mModule = Module.load("/data/local/tmp/dlv3_qnn.pte"); - mButtonHtp.setEnabled(false); - mProgressBar.setVisibility(ProgressBar.VISIBLE); - mButtonHtp.setText(getString(R.string.run_model)); - - Thread thread = new Thread(MainActivity.this); - thread.start(); - } - }); - - final Button resetImage = findViewById(R.id.resetImage); - resetImage.setOnClickListener( - new View.OnClickListener() { - public void onClick(View v) { - populateImage(); - } - }); - } - - @Override - public void run() { - final Tensor inputTensor = - TensorImageUtils.bitmapToFloat32Tensor( - mBitmap, - TensorImageUtils.TORCHVISION_NORM_MEAN_RGB, - TensorImageUtils.TORCHVISION_NORM_STD_RGB); - final float[] inputs = inputTensor.getDataAsFloatArray(); - - final long startTime = SystemClock.elapsedRealtime(); - Tensor outputTensor = mModule.forward(EValue.from(inputTensor))[0].toTensor(); - final long inferenceTime = SystemClock.elapsedRealtime() - startTime; - Log.d("ImageSegmentation", "inference time (ms): " + inferenceTime); - - final float[] scores = outputTensor.getDataAsFloatArray(); - int width = mBitmap.getWidth(); - int height = mBitmap.getHeight(); - - int[] intValues = new int[width * height]; - for (int j = 0; j < height; j++) { - for (int k = 0; k < width; k++) { - int maxi = 0, maxj = 0, maxk = 0; - double maxnum = -Double.MAX_VALUE; - for (int i = 0; i < CLASSNUM; i++) { - float score = scores[i * (width * height) + j * width + k]; - if (score > maxnum) { - maxnum = score; - maxi = i; - maxj = j; - maxk = k; - } - } - if (maxi == PERSON) intValues[maxj * width + maxk] = 0xFFFF0000; // R - else if (maxi == DOG) intValues[maxj * width + maxk] = 0xFF00FF00; // G - else if (maxi == SHEEP) intValues[maxj * width + maxk] = 0xFF0000FF; // B - else intValues[maxj * width + maxk] = 0xFF000000; - } - } - - Bitmap bmpSegmentation = Bitmap.createScaledBitmap(mBitmap, width, height, true); - Bitmap outputBitmap = bmpSegmentation.copy(bmpSegmentation.getConfig(), true); - outputBitmap.setPixels( - intValues, - 0, - outputBitmap.getWidth(), - 0, - 0, - outputBitmap.getWidth(), - outputBitmap.getHeight()); - final Bitmap transferredBitmap = - Bitmap.createScaledBitmap(outputBitmap, mBitmap.getWidth(), mBitmap.getHeight(), true); - - runOnUiThread( - new Runnable() { - @Override - public void run() { - mImageView.setImageBitmap(transferredBitmap); - mButtonXnnpack.setEnabled(true); - mButtonXnnpack.setText(R.string.run_xnnpack); - mButtonHtp.setEnabled(true); - mButtonHtp.setText(R.string.run_htp); - mProgressBar.setVisibility(ProgressBar.INVISIBLE); - } - }); - } -} diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/java/com/example/executorchdemo/TensorImageUtils.java b/examples/demo-apps/android/ExecuTorchDemo/app/src/main/java/com/example/executorchdemo/TensorImageUtils.java deleted file mode 100644 index a5c7699df9f..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/java/com/example/executorchdemo/TensorImageUtils.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.example.executorchdemo; - -import android.graphics.Bitmap; -import android.util.Log; -import java.nio.FloatBuffer; -import org.pytorch.executorch.Tensor; - -/** - * Contains utility functions for {@link Tensor} creation from {@link android.graphics.Bitmap} or - * {@link android.media.Image} source. - */ -public final class TensorImageUtils { - - public static float[] TORCHVISION_NORM_MEAN_RGB = new float[] {0.485f, 0.456f, 0.406f}; - public static float[] TORCHVISION_NORM_STD_RGB = new float[] {0.229f, 0.224f, 0.225f}; - - /** - * Creates new {@link Tensor} from full {@link android.graphics.Bitmap}, normalized with specified - * in parameters mean and std. - * - * @param normMeanRGB means for RGB channels normalization, length must equal 3, RGB order - * @param normStdRGB standard deviation for RGB channels normalization, length must equal 3, RGB - * order - */ - public static Tensor bitmapToFloat32Tensor( - final Bitmap bitmap, final float[] normMeanRGB, final float normStdRGB[]) { - checkNormMeanArg(normMeanRGB); - checkNormStdArg(normStdRGB); - - return bitmapToFloat32Tensor( - bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), normMeanRGB, normStdRGB); - } - - /** - * Writes tensor content from specified {@link android.graphics.Bitmap}, normalized with specified - * in parameters mean and std to specified {@link java.nio.FloatBuffer} with specified offset. - * - * @param bitmap {@link android.graphics.Bitmap} as a source for Tensor data - * @param x - x coordinate of top left corner of bitmap's area - * @param y - y coordinate of top left corner of bitmap's area - * @param width - width of bitmap's area - * @param height - height of bitmap's area - * @param normMeanRGB means for RGB channels normalization, length must equal 3, RGB order - * @param normStdRGB standard deviation for RGB channels normalization, length must equal 3, RGB - * order - */ - public static void bitmapToFloatBuffer( - final Bitmap bitmap, - final int x, - final int y, - final int width, - final int height, - final float[] normMeanRGB, - final float[] normStdRGB, - final FloatBuffer outBuffer, - final int outBufferOffset) { - checkOutBufferCapacity(outBuffer, outBufferOffset, width, height); - checkNormMeanArg(normMeanRGB); - checkNormStdArg(normStdRGB); - final int pixelsCount = height * width; - final int[] pixels = new int[pixelsCount]; - bitmap.getPixels(pixels, 0, width, x, y, width, height); - final int offset_g = pixelsCount; - final int offset_b = 2 * pixelsCount; - for (int i = 0; i < 100; i++) { - final int c = pixels[i]; - Log.i("Image", ": " + i + " " + ((c >> 16) & 0xff)); - } - for (int i = 0; i < pixelsCount; i++) { - final int c = pixels[i]; - float r = ((c >> 16) & 0xff) / 255.0f; - float g = ((c >> 8) & 0xff) / 255.0f; - float b = ((c) & 0xff) / 255.0f; - outBuffer.put(outBufferOffset + i, (r - normMeanRGB[0]) / normStdRGB[0]); - outBuffer.put(outBufferOffset + offset_g + i, (g - normMeanRGB[1]) / normStdRGB[1]); - outBuffer.put(outBufferOffset + offset_b + i, (b - normMeanRGB[2]) / normStdRGB[2]); - } - } - - /** - * Creates new {@link Tensor} from specified area of {@link android.graphics.Bitmap}, normalized - * with specified in parameters mean and std. - * - * @param bitmap {@link android.graphics.Bitmap} as a source for Tensor data - * @param x - x coordinate of top left corner of bitmap's area - * @param y - y coordinate of top left corner of bitmap's area - * @param width - width of bitmap's area - * @param height - height of bitmap's area - * @param normMeanRGB means for RGB channels normalization, length must equal 3, RGB order - * @param normStdRGB standard deviation for RGB channels normalization, length must equal 3, RGB - * order - */ - public static Tensor bitmapToFloat32Tensor( - final Bitmap bitmap, - int x, - int y, - int width, - int height, - float[] normMeanRGB, - float[] normStdRGB) { - checkNormMeanArg(normMeanRGB); - checkNormStdArg(normStdRGB); - - final FloatBuffer floatBuffer = Tensor.allocateFloatBuffer(3 * width * height); - bitmapToFloatBuffer(bitmap, x, y, width, height, normMeanRGB, normStdRGB, floatBuffer, 0); - return Tensor.fromBlob(floatBuffer, new long[] {1, 3, height, width}); - } - - private static void checkOutBufferCapacity( - FloatBuffer outBuffer, int outBufferOffset, int tensorWidth, int tensorHeight) { - if (outBufferOffset + 3 * tensorWidth * tensorHeight > outBuffer.capacity()) { - throw new IllegalStateException("Buffer underflow"); - } - } - - private static void checkTensorSize(int tensorWidth, int tensorHeight) { - if (tensorHeight <= 0 || tensorWidth <= 0) { - throw new IllegalArgumentException("tensorHeight and tensorWidth must be positive"); - } - } - - private static void checkRotateCWDegrees(int rotateCWDegrees) { - if (rotateCWDegrees != 0 - && rotateCWDegrees != 90 - && rotateCWDegrees != 180 - && rotateCWDegrees != 270) { - throw new IllegalArgumentException("rotateCWDegrees must be one of 0, 90, 180, 270"); - } - } - - private static void checkNormStdArg(float[] normStdRGB) { - if (normStdRGB.length != 3) { - throw new IllegalArgumentException("normStdRGB length must be 3"); - } - } - - private static void checkNormMeanArg(float[] normMeanRGB) { - if (normMeanRGB.length != 3) { - throw new IllegalArgumentException("normMeanRGB length must be 3"); - } - } -} diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/res/drawable/ic_launcher_background.xml b/examples/demo-apps/android/ExecuTorchDemo/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9cbf1..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/res/drawable/ic_launcher_foreground.xml b/examples/demo-apps/android/ExecuTorchDemo/app/src/main/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 7706ab9e6d4..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - diff --git a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/res/layout/activity_classification.xml b/examples/demo-apps/android/ExecuTorchDemo/app/src/main/res/layout/activity_classification.xml deleted file mode 100644 index d896adb54d4..00000000000 --- a/examples/demo-apps/android/ExecuTorchDemo/app/src/main/res/layout/activity_classification.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - -