Skip to content

Commit

Permalink
v0.4.0
Browse files Browse the repository at this point in the history
Signed-off-by: QAIHM Team <[email protected]>
  • Loading branch information
qaihm-bot authored and kory committed Mar 18, 2024
1 parent 11b9063 commit 5bae6e8
Show file tree
Hide file tree
Showing 857 changed files with 21,748 additions and 4,591 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.jpg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.jar filter=lfs diff=lfs merge=lfs -text
115 changes: 0 additions & 115 deletions .gitignore

This file was deleted.

118 changes: 67 additions & 51 deletions README.md

Large diffs are not rendered by default.

72 changes: 72 additions & 0 deletions apps/android/ImageClassification/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
### Requirements

1. Java, android-sdk and sdkmanager is already set at user's end
2. User should have Linux QNN SDK in local machine.


## Info
Right now we use mobilenet_v3_small.tflite model which takes 224x224 as input and gives array of 1000 as output. You can replace it with any tflite classification model, but you have to change the pre-processing, post-processing and dimensions in the app code based on model parameters.


## Preprocessing


```
for (int x = 0; x < input_dims1; x++) {
for (int y = 0; y < input_dims2; y++) {
int pixel = inputBitmap.getPixel(x, y);
List<Float> rgb = Arrays.asList((float)Color.red(pixel), (float)Color.green(pixel), (float)Color.blue(pixel));
for(int z = 0;z<3; z++){
floatinputarray[0][z][x][y] = (float)((rgb.get(z))-ImageMean.get(z))/ImageStd.get(z);
}
}
}
```


## PostProcessing


```
public static List<Integer> findTop3Indices(float[] arr) {
List<Integer> topIndices = new ArrayList<>();
for (int i = 0; i < 3; i++) {
int maxIndex = 0;
float maxValue = arr[0];
for (int j = 1; j < arr.length; j++) {
if (arr[j] > maxValue && !topIndices.contains(j)) {
maxValue = arr[j];
maxIndex = j;
}
}
topIndices.add(maxIndex);
}
return topIndices;
}
```

### Build App:

You have to run build_apk.py for Image Classification. It will generate classification-debug.apk and install it in connected device.


build_apk.py [-h] -q QNNSDK (-m MODEL_PATH | -e MODEL_NAME)



### Example

Here, with -m, give your tflite model path i.e. till `*.tflite file`, and it will copy model file to assets folder to build andoid app.
```
python build_apk.py -q "<QNN_SDK_PATH>" -m "Path\to\TFLITE\Model"
```

Also, you can use AI-HUB Model name as mentioned in models directory, to directly export the model from AI-Hub and copy it to app assets.

```
python build_apk.py -q "<QNN_SDK_PATH>" -e <Model Name>
```
10 changes: 10 additions & 0 deletions apps/android/ImageClassification/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.2.1' apply false
id 'com.android.library' version '7.2.1' apply false
}

task clean(type: Delete) {
delete rootProject.buildDir
}
163 changes: 163 additions & 0 deletions apps/android/ImageClassification/build_apk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# ---------------------------------------------------------------------
# Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
# ---------------------------------------------------------------------
import argparse
import glob
import os
import shutil
import subprocess
import sys
from enum import Enum


class MODELNAME(Enum):
mobilenet_v3_large = 1
resnet50 = 2
resnext50 = 3
inception_v3 = 4


def printmenu():
print("*****************************")
print("* TYPE OF MODEL *")
print("*****************************")
for m in MODELNAME:
print(str(m.value) + ". " + m.name)
print("*****************************")


## Initialize parser
parser = argparse.ArgumentParser()
parser.add_argument("-q", "--qnnsdk", required=True, help="Give path of QNN SDK")

parser.add_argument("-m", "--model_name", type=str, help="Model Name")


# group = parser.add_mutually_exclusive_group()
# group.add_argument('-stopdownload', '--stopdownload', action = "store_true", help = "Do NOT Download Model from AI HUB")
parser.add_argument("-path", "--model_path", type=str, help="TFLITE model file")

args = parser.parse_args()


##based on this pre-post can be decided
if not args.model_name:
printmenu()
inp_model_name = int(input("Please select one: "))
args.model_name = MODELNAME(inp_model_name).name


destAsset = os.path.join(".", "classification", "src", "main", "assets")
if not os.path.exists(destAsset):
os.makedirs(destAsset)


## MODEL PATH NOT MENTIONED, add information into model_path
if not args.model_path:
exportstatus = input("Do you want us to download the model from AI hub (y/n)")

##DOWNLAOD USING EXPORT.PY
if exportstatus.lower().startswith("y"):
print("EXPORT form path")
pathtomodel = os.path.join(
"..",
"..",
"..",
"",
"qai_hub_models",
"models",
args.model_name,
"export.py",
)
if not os.path.exists(pathtomodel):
print("PATH DO NOT EXIST: " + pathtomodel)
exit()
subprocess.run(["python", pathtomodel, "--skip-inferencing"])
tflite_file = glob.glob(
"build" + os.sep + args.model_name + os.sep + "*.tflite", recursive=True
)
args.model_path = tflite_file[0]
# shutil.copy(tflite_file[0], destAsset+os.sep+"superresmodel.tflite")

##GET USER TO GIVE PATH
else:
args.model_path = input("Give model File as input")
# if not os.path.exists(tflite_file):
# print("PATH DO NOT EXIST: "+tflite_file)
# exit()
# shutil.copy(tflite_file, destAsset+os.sep+"superresmodel.tflite")


if args.model_path:
print(args.model_path)
if not os.path.exists(args.model_path):
print("PATH DO NOT EXIST: " + args.model_path)
exit()
shutil.copy(args.model_path, destAsset + os.sep + "classification.tflite")


## COPYING REQUIRED FILES FROM QNN SDK
destJNI = os.path.join(".", "classification", "src", "main", "jniLibs", "arm64-v8a")
if not os.path.exists(destJNI):
os.makedirs(destJNI)

# copy *.so from $qnn_sdk/libs/aarch64-android to $jni_lib_dir
qnnbasiclibs = os.path.join(args.qnnsdk, "lib", "aarch64-android")
shutil.copytree(qnnbasiclibs, destJNI, dirs_exist_ok=True)

# copy $qnn_sdk/lib/hexagon-v**/unsigned/libQnnHtpV**Skel.so to $jni_lib_dir
skelstubfiles = os.path.join(args.qnnsdk, "lib", "hexagon-v**", "unsigned", "*.so")
for file in glob.glob(skelstubfiles):
shutil.copy(file, destJNI)

# copy qtld-release.aar to $test_app_root/Application/
destaar = os.path.join(".", "classification", "libs")
if not os.path.exists(destaar):
os.makedirs(destaar)
aarfile = os.path.join(args.qnnsdk, "lib", "android", "qtld-release.aar")
shutil.copy(aarfile, destaar)


## BUILDING APK
if sys.platform.startswith("win"):
print("Detected platform is windows")
gradleoutput = subprocess.run(["gradlew.bat", "assembleDebug"], cwd=".")
elif sys.platform.startswith("darwin"):
print("Detected platform is MAC")
gradleoutput = subprocess.run(["./gradlew", "assembleDebug"], cwd=".")
else:
print("Detected platform is Linux")
gradleoutput = subprocess.run(["./gradlew", "assembleDebug"], cwd=".")


## COPYING APK TO CWD
ApkPath = os.path.join(
os.getcwd(),
"classification",
"build",
"outputs",
"apk",
"debug",
"classification-debug.apk",
)
print("APK Is copied at current Working Directory")
shutil.copy(ApkPath, ".")


install_perm = input("Do you want to install this apk in connected device")
## INSTALLING AND RUNNING APK
if install_perm.lower().startswith("y"):
command_to_install = ["adb", "install", "classification-debug.apk"]
subprocess.run(command_to_install, cwd=".")
command_to_run = [
"adb",
"shell",
"am",
"start",
"-a",
"com.example.ACTION_NAME",
"-n",
"com.qcom.imagesuperres/com.qcom.imagesuperres.QNNActivity",
]
subprocess.run(command_to_run, cwd=".")
Loading

0 comments on commit 5bae6e8

Please sign in to comment.