Skip to main content
This tutorial adds the Qualcomm AI Engine Direct (QNN) TFLite delegate to an Edge Impulse object detection app, so inference runs on the Hexagon NPU of Snapdragon devices. It builds on Camera inference on Android. The reference code is in qnn-hardware-acceleration.
Qualcomm AI Engine Direct stack showing the TensorFlow Lite delegate layer between the app and QNN backends

Where the QNN TFLite delegate fits in the Qualcomm AI Engine Direct stack

What you’ll build

An Android app that:
  • Runs an Edge Impulse object detection model on frames from the Camera2 API
  • Runs inference on the Hexagon NPU (HTP) through the QNN delegate
  • Draws bounding boxes over the camera preview
  • Logs timing for each stage to Logcat

Performance

The app logs the DSP and inference time for each frame to Logcat, so you can compare runs with and without the delegate on your own device and model:
Logcat output with CPU inference timing before enabling the QNN delegate

Logcat timing without QNN acceleration

HTP acceleration requires an INT8 quantized model. Performance depends on the device SoC, the model architecture, and how many of the model’s operations QNN supports.

Prerequisites

  • A trained Edge Impulse object detection model
  • Android Studio Ladybug 2024.2.2 or later, with Android API 35, NDK 27.0.12077973, and CMake 3.22.1
  • The Qualcomm AI Engine Direct SDK
  • A Snapdragon device with a Hexagon NPU, or access to one through Qualcomm Device Cloud

Supported devices

QNN acceleration needs a Qualcomm Hexagon NPU Gen 2 or later:
Snapdragon reference phone displayed above its device specifications

Example Snapdragon reference device used for testing

Google Tensor processors don’t include a Hexagon NPU, so QNN acceleration doesn’t work on Pixel devices.

1. Clone the repository

Open the project in Android Studio and let the Gradle and NDK sync finish.

2. Find the QNN delegate in the SDK

Install the Qualcomm AI Engine Direct SDK. It’s usually installed in one of these locations:
Find the Android arm64 copy of libQnnTFLiteDelegate.so. On macOS or Linux:
On Windows, open C:\qairt\<version>\ in File Explorer and search for libQnnTFLiteDelegate.so. The folder that contains it also holds the other libQnn*.so runtime libraries. You copy from this folder in the next step.

3. Copy the QNN libraries

Create the destination folder:
Copy these libraries from the delegate folder into app/src/main/jniLibs/arm64-v8a/:
The repository includes a script that copies the libraries. Set your QAIRT SDK path in the script first, then run it:

4. Deploy your model

  1. In Edge Impulse Studio, go to Deployment.
  2. Select Android (C++ library).
  3. Select the Quantized (int8) model.
  4. Click Build and download the .zip file.
Extract it into the project:

5. Configure the Android manifest

In app/src/main/AndroidManifest.xml, set extractNativeLibs and declare libcdsprpc.so so the app can load the QNN libraries:

6. Build and run

  1. Connect your Snapdragon device over USB and enable USB debugging in Developer options.
  2. In Android Studio, click Run and select your device.
Filter Logcat by MainActivity to see the timing for each stage:
To confirm that the app loaded the QNN libraries, check its memory maps:
If the output lists QNN library paths, acceleration is active.

How it works

Load the QNN delegate

native-lib.cpp sets the library search paths, then loads the QNN TFLite delegate with the HTP backend:

Set the environment

MainActivity.kt points the library paths at the app’s native library folder on startup:

Project structure

Customization

Change the HTP performance mode

Set htp_performance_mode in the QNN options in native-lib.cpp:

Enable profiling

Set profiling_level to write a profile to /sdcard/qnn_profile.json:

Change the detection threshold

A higher threshold gives fewer false positives. A lower one gives more detections:

Performance tuning

Model

  • Use INT8 quantization. HTP acceleration requires it.
  • Reduce the input resolution. A 320×320 input has a quarter of the pixels of a 640×640 input.
  • Use fewer layers, and check which operations run on the HTP and which fall back to the CPU. See the QNN operator support list.

Runtime

Frame rate

If processing can’t keep up with the camera, lower the camera frame rate:

Next steps

Resources