# Mobilenet V2 Inference on HTP This tutorial shows how to convert and execute a MobileNetV2 model on the QAIRT HTP Backend. It includes a step-by-step breakdown of the process. You can copy each snippet into a single script to run the tutorial end to end. Note If you would like to skip the breakdown, you can obtain a simplified version of the tutorial in the QAIRT SDK from the following path: > > > - `examples/QAIRT/python/basic_tutorial.py` The parameters for this tutorial are as follows: > > > - Framework: PyTorch > - Model: [MobileNetV2](https://pytorch.org/hub/pytorch_vision_mobilenet_v2) > - Configurations: > > - Host OS: Linux (x86\_64) > - Target Devices: Snapdragon Android Device > - Processor: Qualcomm NPU > - Backend: HTP Tip This tutorial creates some temporary files as part of the workflow. To customize the temporary file location, set the env variable *QAIRT\_TMP\_DIR* to a location of your choosing. ## Step 1. Setup First, import the necessary libraries that will be used in this tutorial. Ensure you have the QAIRT SDK installed and that the **qairt** package is available. If you see any import errors, follow the setup instructions to install the QAIRT SDK here: [Setup](https://docs.qualcomm.com/bundle/publicresource/topics/80-63442-50/setup.html) import json import os import platform from pathlib import Path import numpy as np import requests import torch import torchvision.transforms as transforms from PIL import Image import qairt from qairt import CompileConfig, Device, DevicePlatformType, ExecutionResult, RemoteDeviceIdentifier Copy to clipboard ## Step 2. Get a MobileNetV2 model Download the MobileNetV2 model from PyTorch Hub. pytorch_model = torch.hub.load("pytorch/vision:v0.10.0", "mobilenet_v2", pretrained=True) pytorch_model.eval() # Create a directory for artifacts artifacts_dir = Path("./mobilenetv2_artifacts").resolve() artifacts_dir.mkdir(parents=True, exist_ok=True) onnx_model_path = str(artifacts_dir / "mobilenet_v2.onnx") # Export the PyTorch model as an ONNX model dummy_input = torch.rand((1, 3, 224, 224), dtype=torch.float32) torch.onnx.export( pytorch_model, (dummy_input,), onnx_model_path, input_names=["input"], output_names=["output"], opset_version=11, ) Copy to clipboard ## Step 3. Convert the model Once the model is exported, we can proceed to convert it using QAIRT. converted_model: qairt.Model = qairt.convert(onnx_model_path) Copy to clipboard The convert API produces a [`qairt.Model`](https://docs.qualcomm.com/doc/80-87189-2/topic/qairt-core-api.html#qairt.Model) object which can be executed and saved to disk. You can pass in extra options to the convert API as keyword arguments. ## Step 4. Compile the model The next step after conversion and/or quantization is to compile the model ahead of time. While this step is optional, it is recommended to avoid preparation time costs on the target device. Converted models can be compiled using: compiled_model: qairt.CompiledModel = qairt.compile(converted_model, backend="HTP") Copy to clipboard If you know the target device ahead, you may customize the compilation process using a `qairt.api.config.CompileConfig` object. For example, to compile for Snapdragon 8 Elite (SM8750) android device, you can use the following config: config = CompileConfig(backend="HTP", soc_details="chipset:SM8750") Copy to clipboard If you are not using “SM8750” as the target device, see this link for a list of supported chipsets - [Chipsets](https://docs.qualcomm.com/bundle/publicresource/topics/80-63442-50/overview.html#supported-snapdragon-devices) to obtain the chipset for your device. Next, we can compile the model using the config object: compiled_model: qairt.CompiledModel = qairt.compile(converted_model, config=config) # print the information from the model print(json.dumps(compiled_model.module.info.as_dict(), indent=4)) Copy to clipboard The compilation process will produce a [`qairt.api.compiled_model.CompiledModel`](https://docs.qualcomm.com/doc/80-87189-2/topic/qairt-core-api.html#qairt.CompiledModel) object. You should see information about the compiled model below: { "name": "mobilenet_v2", "graphs": [ { "name": "mobilenet_v2", "inputs": [ { "name": "input", "dimensions": [ 1, 3, 224, 224 ], "data_type": "QNN_DATATYPE_FLOAT_32" } ], "outputs": [ { "name": "output", "dimensions": [ 1, 1000 ], "data_type": "QNN_DATATYPE_FLOAT_32" } ] } ], "soc_name": "69", "backend": "HTP", "backend_info": { "arch": 79, "vtcm_size": 4, "optimization_level": 0 } } Copy to clipboard ## Step 5. Set up an Android device This section detects the ANDROID\_SERIAL variable which is expected to map to the ADB id for your android devices. You can obtain the ADB id for your device by running the following command: adb devices Copy to clipboard The output should look like this: List of devices attached abcd1234 device Copy to clipboard You can set the ANDROID\_SERIAL to the id above - export ANDROID_SERIAL=abcd1234 Copy to clipboard If your device is not connected to a different remote machine, you would not see a device listed above. In this case, you should ensure an **ADB** connection is established on the other machine. Run this command on the remote machine: adb -a nodaemon server start Copy to clipboard Then, on your local machine, run this command: adb -H devices Copy to clipboard The output should now look like this: List of devices attached abcd1234 device Copy to clipboard Set the hostname to an environment variable: export ANDROID_HOSTNAME= Copy to clipboard ## Step 6. Create a device Before we can run the model on the device, we need to create a `qairt.api.device.Device` object. The object encapsulates the connection to the Android device via ADB. android_serial = os.getenv("ANDROID_SERIAL") android_hostname = os.getenv("ANDROID_HOSTNAME") android_device = None if android_serial: if android_hostname: android_device = Device(identifier=f"{android_serial}@{android_hostname}", type=DevicePlatformType.ANDROID) else: android_device = Device(identifier=android_serial, type=DevicePlatformType.ANDROID) else: print("INFO: ANDROID_SERIAL was not found. Exiting") exit(1) Copy to clipboard ## Step 7. Executing on device The QAIRT SDK includes a set of sample images of shape : (3 x H x W) where H and W are at least of dimension: 224 x 224 We will use these images to execute the compiled model on the device. image_location = os.path.join(os.environ["QAIRT_SDK_ROOT"], "examples", "QAIRT", "python", "images") IMAGE_DATASET = { "african elephant": os.path.join(image_location, "african_elephant.jpg"), "samoyed": os.path.join(image_location, "samoyed.jpg"), "sea lion": os.path.join(image_location, "sea_lion.jpg") } Copy to clipboard Each image is loaded in a range of [0,1] and then normalized using mean: [0.485, 0.456, 0.406] and std: [0.229, 0.224, 0.225] # To make things simpler, we can define a simple function to preprocess each image. def preprocess_input(image: str) -> np.ndarray: image_obj = Image.open(image) preprocess = transforms.Compose( [ transforms.Resize(224), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ] ) tensor = preprocess(image_obj).unsqueeze(0) return tensor.numpy() Copy to clipboard We can now execute the model on the target device specified above using the images from the dataset. Data may also be passed in as dictionary of name to numpy array. outputs = [] for label, image_url in IMAGE_DATASET.items(): image: np.ndarray = preprocess_input(image_url) result: ExecutionResult = compiled_model(image, device=android_device) _, output_tensors = compiled_model.output_tensors[0] outputs.append((result[output_tensors[0].name], label)) Copy to clipboard ## Step 8. Post-Processing For post-processing, will use imagenet labels obtained from [Qualcomm AI Hub](https://qaihub-public-assets.s3.us-west-2.amazonaws.com/apidoc/imagenet_classes.txt) Here is a small snippet of code that computes softmax probabilities from the output and prints the top-5 predictions using the class labels. def postprocess_results(output_ndarray: np.ndarray) -> str: # Softmax function on_device_probabilities = np.exp(output_ndarray) / np.sum(np.exp(output_ndarray), axis=1) # Read the ImageNet class labels sample_classes = "https://qaihub-public-assets.s3.us-west-2.amazonaws.com/apidoc/imagenet_classes.txt" response = requests.get(sample_classes, stream=True, timeout=5) response.raw.decode_content = True categories = [s.strip().decode("utf-8") for s in response.raw] # Print the top five predictions print("Top-5 predictions:") top5_classes = np.argsort(on_device_probabilities[0], axis=0)[-5:] prediction = categories[top5_classes[-1]] for c in reversed(top5_classes): print(f"{c} {categories[c]:20s} {on_device_probabilities[0][c]:>6.1%}") print() return prediction Copy to clipboard The code below prints predictions for each image in the dataset. for arr, label in outputs: # Postprocess the results prediction = postprocess_results(arr) prediction = prediction.lower() label = label.lower() if prediction == label: print(f"Successful prediction: {prediction}\n") else: print(f"Failed prediction: {prediction}. Expected {label}\n") Copy to clipboard Top-5 predictions: 386 African elephant 84.8% 385 Indian elephant 6.6% 101 tusker 4.7% 346 water buffalo 2.6% 343 warthog 0.5% Successful prediction: african elephant Top-5 predictions: 258 Samoyed 81.3% 259 Pomeranian 7.6% 261 keeshond 2.0% 279 Arctic fox 1.8% 257 Great Pyrenees 1.4% Successful prediction: samoyed Top-5 predictions: 150 sea lion 99.9% 147 grey whale 0.0% 360 otter 0.0% 460 breakwater 0.0% 146 albatross 0.0% Successful prediction: sea lion Copy to clipboard We can see that the model is able to correctly predict the labels for the images provided. This shows that the model is executing correctly on the target device. ## Step 9. Save the compiled model We can also save the compiled model for future use or deployment. compiled_model.save(artifacts_dir / "mobilenet_v2.bin") Copy to clipboard ### Next Steps > > > - Follow the [Profiling Models with QAIRT Visualizer](https://docs.qualcomm.com/doc/80-87189-2/topic/profiling_models_with_visualizer.html#profiling-models-android-visualizer) tutorial to analyze and visualize profiling results. Profiling can > help you identify bottlenecks and optimize your model for better performance. Last Published: Aug 19, 2026 [Previous Topic For Android devices](https://docs.qualcomm.com/bundle/publicresource/80-87189-2/topics/tutorials.md) [Next Topic Profiling Models with QAIRT Visualizer](https://docs.qualcomm.com/bundle/publicresource/80-87189-2/topics/profiling_models_with_visualizer.md)