1*89c4ff92SAndroid Build Coastguard Worker# PyArmNN 2*89c4ff92SAndroid Build Coastguard Worker 3*89c4ff92SAndroid Build Coastguard WorkerPyArmNN is a python extension for [Arm NN SDK](https://developer.arm.com/ip-products/processors/machine-learning/arm-nn). 4*89c4ff92SAndroid Build Coastguard WorkerPyArmNN provides interface similar to Arm NN C++ Api. 5*89c4ff92SAndroid Build Coastguard WorkerBefore you proceed with the project setup, you will need to checkout and build a corresponding Arm NN version. 6*89c4ff92SAndroid Build Coastguard Worker 7*89c4ff92SAndroid Build Coastguard WorkerPyArmNN is built around public headers from the armnn/include folder of Arm NN. PyArmNN does not implement any computation kernels itself, all operations are 8*89c4ff92SAndroid Build Coastguard Workerdelegated to the Arm NN library. 9*89c4ff92SAndroid Build Coastguard Worker 10*89c4ff92SAndroid Build Coastguard WorkerThe [SWIG](http://www.swig.org/) project is used to generate the Arm NN python shadow classes and C wrapper. 11*89c4ff92SAndroid Build Coastguard Worker 12*89c4ff92SAndroid Build Coastguard WorkerThe following diagram shows the conceptual architecture of this library: 13*89c4ff92SAndroid Build Coastguard Worker 14*89c4ff92SAndroid Build Coastguard Worker 15*89c4ff92SAndroid Build Coastguard Worker# Setup development environment 16*89c4ff92SAndroid Build Coastguard Worker 17*89c4ff92SAndroid Build Coastguard WorkerBefore, proceeding to the next steps, make sure that: 18*89c4ff92SAndroid Build Coastguard Worker 19*89c4ff92SAndroid Build Coastguard Worker1. You have Python 3.6+ installed system-side. The package is not compatible with older Python versions. 20*89c4ff92SAndroid Build Coastguard Worker2. You have python3.6-dev installed system-side. This contains header files needed to build PyArmNN extension module. 21*89c4ff92SAndroid Build Coastguard Worker3. In case you build Python from sources manually, make sure that the following libraries are installed and available in you system: 22*89c4ff92SAndroid Build Coastguard Worker``python3.6-dev build-essential checkinstall libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev`` 23*89c4ff92SAndroid Build Coastguard Worker4. Install SWIG 4.x. Only 3.x version is typically available in Linux package managers, so you will have to build it and install it from sources. It can be downloaded from the [SWIG project website](http://www.swig.org/download.html) or from [SWIG GitHub](https://github.com/swig/swig). To install it follow the guide on [SWIG GitHub](https://github.com/swig/swig/wiki/Getting-Started). 24*89c4ff92SAndroid Build Coastguard Worker 25*89c4ff92SAndroid Build Coastguard Worker## Setup virtual environment 26*89c4ff92SAndroid Build Coastguard Worker 27*89c4ff92SAndroid Build Coastguard WorkerNow you can proceed with setting up workspace. It is recommended to create a python virtual environment, so you do not pollute your working folder: 28*89c4ff92SAndroid Build Coastguard Worker```bash 29*89c4ff92SAndroid Build Coastguard Workerpython -m venv env 30*89c4ff92SAndroid Build Coastguard Workersource env/bin/activate 31*89c4ff92SAndroid Build Coastguard Worker``` 32*89c4ff92SAndroid Build Coastguard Worker 33*89c4ff92SAndroid Build Coastguard WorkerYou may run into missing python modules such as *wheel*. Make sure to install those using pip: 34*89c4ff92SAndroid Build Coastguard Worker```bash 35*89c4ff92SAndroid Build Coastguard Workerpip install wheel 36*89c4ff92SAndroid Build Coastguard Worker``` 37*89c4ff92SAndroid Build Coastguard Worker 38*89c4ff92SAndroid Build Coastguard Worker## Build python distr 39*89c4ff92SAndroid Build Coastguard Worker 40*89c4ff92SAndroid Build Coastguard WorkerPython supports source and binary distribution packages. 41*89c4ff92SAndroid Build Coastguard Worker 42*89c4ff92SAndroid Build Coastguard WorkerSource distr contains setup.py script that is executed on the users machine during package installation. 43*89c4ff92SAndroid Build Coastguard WorkerWhen preparing binary distr (wheel), setup.py is executed on the build machine and the resulting package contains only the result 44*89c4ff92SAndroid Build Coastguard Workerof the build (generated files and resources, test results etc). 45*89c4ff92SAndroid Build Coastguard Worker 46*89c4ff92SAndroid Build Coastguard WorkerIn our case, PyArmNN depends on Arm NN installation. Thus, binary distr will be linked with 47*89c4ff92SAndroid Build Coastguard Workerthe local build machine libraries and runtime. 48*89c4ff92SAndroid Build Coastguard Worker 49*89c4ff92SAndroid Build Coastguard WorkerThe recommended way to build the python packages is by CMake. 50*89c4ff92SAndroid Build Coastguard Worker 51*89c4ff92SAndroid Build Coastguard Worker### CMake build 52*89c4ff92SAndroid Build Coastguard Worker 53*89c4ff92SAndroid Build Coastguard WorkerThe recommended approach is to build PyArmNN together with Arm NN by adding the following options to your CMake command: 54*89c4ff92SAndroid Build Coastguard Worker``` 55*89c4ff92SAndroid Build Coastguard Worker-DBUILD_PYTHON_SRC=1 56*89c4ff92SAndroid Build Coastguard Worker``` 57*89c4ff92SAndroid Build Coastguard WorkerThis will build the source package. Current project headers and build libraries will be used, so there is no need to provide them. 58*89c4ff92SAndroid Build Coastguard Worker 59*89c4ff92SAndroid Build Coastguard WorkerSWIG is required to generate the wrappers. If CMake did not find the executable during the configure step or it has found an older version, you may provide it manually: 60*89c4ff92SAndroid Build Coastguard Worker``` 61*89c4ff92SAndroid Build Coastguard Worker-DSWIG_EXECUTABLE=<path_to_swig_executable> 62*89c4ff92SAndroid Build Coastguard Worker``` 63*89c4ff92SAndroid Build Coastguard Worker 64*89c4ff92SAndroid Build Coastguard WorkerAfter the build finishes, you will find the python packages in `<build_folder>/python/pyarmnn/dist`. 65*89c4ff92SAndroid Build Coastguard Worker 66*89c4ff92SAndroid Build Coastguard Worker# PyArmNN installation 67*89c4ff92SAndroid Build Coastguard Worker 68*89c4ff92SAndroid Build Coastguard WorkerPyArmNN can be distributed as a source package or a binary package (wheel). 69*89c4ff92SAndroid Build Coastguard Worker 70*89c4ff92SAndroid Build Coastguard WorkerBinary package is platform dependent, the name of the package will indicate the platform it was built for, e.g.: 71*89c4ff92SAndroid Build Coastguard Worker 72*89c4ff92SAndroid Build Coastguard Worker* Linux x86 64bit machine: pyarmnn-32.0.0-cp36-cp36m-*linux_x86_64*.whl 73*89c4ff92SAndroid Build Coastguard Worker* Linux Aarch 64 bit machine: pyarmnn-32.0.0-cp36-cp36m-*linux_aarch64*.whl 74*89c4ff92SAndroid Build Coastguard Worker 75*89c4ff92SAndroid Build Coastguard WorkerThe source package is platform independent but installation involves compilation of Arm NN python extension. You will need to have g++ compatible with C++ 14 standard and a python development library installed on the build machine. 76*89c4ff92SAndroid Build Coastguard Worker 77*89c4ff92SAndroid Build Coastguard WorkerBoth of them, source and binary package, require the Arm NN library to be present on the target/build machine. 78*89c4ff92SAndroid Build Coastguard Worker 79*89c4ff92SAndroid Build Coastguard WorkerIt is strongly suggested to work within a python virtual environment. The further steps assume that the virtual environment was created and activated before running PyArmNN installation commands. 80*89c4ff92SAndroid Build Coastguard Worker 81*89c4ff92SAndroid Build Coastguard WorkerPyArmNN also depends on the NumPy python library. It will be automatically downloaded and installed alongside PyArmNN. If your machine does not have access to Python pip repositories you might need to install NumPy in advance by following public instructions: https://scipy.org/install.html 82*89c4ff92SAndroid Build Coastguard Worker 83*89c4ff92SAndroid Build Coastguard Worker## Installing from source package 84*89c4ff92SAndroid Build Coastguard Worker 85*89c4ff92SAndroid Build Coastguard WorkerInstalling from source is the most reliable way. 86*89c4ff92SAndroid Build Coastguard Worker 87*89c4ff92SAndroid Build Coastguard WorkerWhile installing from sources, you have the freedom of choosing Arm NN libraries location. Set environment variables *ARMNN_LIB* and *ARMNN_INCLUDE* to point to Arm NN libraries and headers. 88*89c4ff92SAndroid Build Coastguard WorkerIf you want to use system default locations, just set *ARMNN_INCLUDE* to point to Arm NN headers. 89*89c4ff92SAndroid Build Coastguard WorkerAdditionally, *LD_LIBRARY_PATH* may need to be updated to the Arm NN libraries location due to dependencies of the same shared library files being 'not found'. 90*89c4ff92SAndroid Build Coastguard Worker 91*89c4ff92SAndroid Build Coastguard Worker```bash 92*89c4ff92SAndroid Build Coastguard Worker$ export ARMNN_LIB=/path/to/libs 93*89c4ff92SAndroid Build Coastguard Worker$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/libs 94*89c4ff92SAndroid Build Coastguard Worker$ export ARMNN_INCLUDE=/full/path/to/armnn/include:/full/path/to/armnn/profiling/common/include 95*89c4ff92SAndroid Build Coastguard Worker``` 96*89c4ff92SAndroid Build Coastguard Worker 97*89c4ff92SAndroid Build Coastguard WorkerInstall PyArmNN as follows: 98*89c4ff92SAndroid Build Coastguard Worker```bash 99*89c4ff92SAndroid Build Coastguard Worker$ pip install /path/to/armnn/python/pyarmnn 100*89c4ff92SAndroid Build Coastguard Worker``` 101*89c4ff92SAndroid Build Coastguard Worker 102*89c4ff92SAndroid Build Coastguard WorkerIf PyArmNN installation script fails to find Arm NN libraries it will raise an error like this 103*89c4ff92SAndroid Build Coastguard Worker 104*89c4ff92SAndroid Build Coastguard Worker`RuntimeError: ArmNN library was not found in ('/usr/lib/gcc/aarch64-linux-gnu/8/', <...> ,'/lib/', '/usr/lib/'). Please install ArmNN to one of the standard locations or set correct ARMNN_INCLUDE and ARMNN_LIB env variables.` 105*89c4ff92SAndroid Build Coastguard Worker 106*89c4ff92SAndroid Build Coastguard WorkerYou can now verify that PyArmNN library is installed and check PyArmNN version using: 107*89c4ff92SAndroid Build Coastguard Worker```bash 108*89c4ff92SAndroid Build Coastguard Worker$ pip show pyarmnn 109*89c4ff92SAndroid Build Coastguard Worker``` 110*89c4ff92SAndroid Build Coastguard WorkerYou can also verify it by running the following and getting output similar to below: 111*89c4ff92SAndroid Build Coastguard Worker```bash 112*89c4ff92SAndroid Build Coastguard Worker$ python -c "import pyarmnn as ann;print(ann.GetVersion())" 113*89c4ff92SAndroid Build Coastguard Worker'32.0.0' 114*89c4ff92SAndroid Build Coastguard Worker``` 115*89c4ff92SAndroid Build Coastguard Worker 116*89c4ff92SAndroid Build Coastguard Worker 117*89c4ff92SAndroid Build Coastguard Worker## Installing PyArmNN while using ArmNN prebuilt binaries 118*89c4ff92SAndroid Build Coastguard Worker 119*89c4ff92SAndroid Build Coastguard WorkerIf you wish to use ArmNN prebuilt binaries from our release page, you will need to generate the PyArmNN SWIG wrappers. 120*89c4ff92SAndroid Build Coastguard Worker 121*89c4ff92SAndroid Build Coastguard WorkerAgain setup your environmental variables along with a virtual environment: 122*89c4ff92SAndroid Build Coastguard Worker 123*89c4ff92SAndroid Build Coastguard Worker```bash 124*89c4ff92SAndroid Build Coastguard Worker$ python -m venv env 125*89c4ff92SAndroid Build Coastguard Worker$ source env/bin/activate 126*89c4ff92SAndroid Build Coastguard Worker 127*89c4ff92SAndroid Build Coastguard Worker$ export ARMNN_LIB=/path/to/libs 128*89c4ff92SAndroid Build Coastguard Worker$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/libs 129*89c4ff92SAndroid Build Coastguard Worker$ export ARMNN_INCLUDE=/full/path/to/armnn/include:/full/path/to/armnn/profiling/common/include 130*89c4ff92SAndroid Build Coastguard Worker``` 131*89c4ff92SAndroid Build Coastguard Worker 132*89c4ff92SAndroid Build Coastguard WorkerThen generate the SWIG wrappers: 133*89c4ff92SAndroid Build Coastguard Worker```bash 134*89c4ff92SAndroid Build Coastguard Worker$ cd armnn/python/pyarmnn/ 135*89c4ff92SAndroid Build Coastguard Worker$ python swig_generate.py -v 136*89c4ff92SAndroid Build Coastguard Worker``` 137*89c4ff92SAndroid Build Coastguard Worker 138*89c4ff92SAndroid Build Coastguard WorkerThen install PyArmNN: 139*89c4ff92SAndroid Build Coastguard Worker```bash 140*89c4ff92SAndroid Build Coastguard Worker# From directory armnn/python/pyarmnn/ 141*89c4ff92SAndroid Build Coastguard Worker$ pip install . 142*89c4ff92SAndroid Build Coastguard Worker``` 143*89c4ff92SAndroid Build Coastguard Worker 144*89c4ff92SAndroid Build Coastguard WorkerAs above, you can verify that PyArmNN library is installed and check PyArmNN version using: 145*89c4ff92SAndroid Build Coastguard Worker```bash 146*89c4ff92SAndroid Build Coastguard Worker$ pip show pyarmnn 147*89c4ff92SAndroid Build Coastguard Worker``` 148*89c4ff92SAndroid Build Coastguard WorkerYou can also verify it by running the following and getting output similar to below: 149*89c4ff92SAndroid Build Coastguard Worker```bash 150*89c4ff92SAndroid Build Coastguard Worker$ python -c "import pyarmnn as ann;print(ann.GetVersion())" 151*89c4ff92SAndroid Build Coastguard Worker'32.0.0' 152*89c4ff92SAndroid Build Coastguard Worker``` 153*89c4ff92SAndroid Build Coastguard Worker 154*89c4ff92SAndroid Build Coastguard Worker# PyArmNN API overview 155*89c4ff92SAndroid Build Coastguard Worker 156*89c4ff92SAndroid Build Coastguard Worker#### Getting started 157*89c4ff92SAndroid Build Coastguard WorkerThe easiest way to begin using PyArmNN is by using the Parsers. We will demonstrate how to use them below: 158*89c4ff92SAndroid Build Coastguard Worker 159*89c4ff92SAndroid Build Coastguard WorkerCreate a parser object and load your model file. 160*89c4ff92SAndroid Build Coastguard Worker```python 161*89c4ff92SAndroid Build Coastguard Workerimport pyarmnn as ann 162*89c4ff92SAndroid Build Coastguard Workerimport imageio 163*89c4ff92SAndroid Build Coastguard Worker 164*89c4ff92SAndroid Build Coastguard Worker# An ONNX parser also exists. 165*89c4ff92SAndroid Build Coastguard Workerparser = ann.ITfLiteParser() 166*89c4ff92SAndroid Build Coastguard Workernetwork = parser.CreateNetworkFromBinaryFile('./model.tflite') 167*89c4ff92SAndroid Build Coastguard Worker``` 168*89c4ff92SAndroid Build Coastguard Worker 169*89c4ff92SAndroid Build Coastguard WorkerGet the input binding information by using the name of the input layer. 170*89c4ff92SAndroid Build Coastguard Worker```python 171*89c4ff92SAndroid Build Coastguard Workerinput_binding_info = parser.GetNetworkInputBindingInfo(0, 'model/input') 172*89c4ff92SAndroid Build Coastguard Worker 173*89c4ff92SAndroid Build Coastguard Worker# Create a runtime object that will perform inference. 174*89c4ff92SAndroid Build Coastguard Workeroptions = ann.CreationOptions() 175*89c4ff92SAndroid Build Coastguard Workerruntime = ann.IRuntime(options) 176*89c4ff92SAndroid Build Coastguard Worker``` 177*89c4ff92SAndroid Build Coastguard WorkerChoose preferred backends for execution and optimize the network. 178*89c4ff92SAndroid Build Coastguard Worker```python 179*89c4ff92SAndroid Build Coastguard Worker# Backend choices earlier in the list have higher preference. 180*89c4ff92SAndroid Build Coastguard WorkerpreferredBackends = [ann.BackendId('CpuAcc'), ann.BackendId('CpuRef')] 181*89c4ff92SAndroid Build Coastguard Workeropt_network, messages = ann.Optimize(network, preferredBackends, runtime.GetDeviceSpec(), ann.OptimizerOptions()) 182*89c4ff92SAndroid Build Coastguard Worker 183*89c4ff92SAndroid Build Coastguard Worker# Load the optimized network into the runtime. 184*89c4ff92SAndroid Build Coastguard Workernet_id, _ = runtime.LoadNetwork(opt_network) 185*89c4ff92SAndroid Build Coastguard Worker``` 186*89c4ff92SAndroid Build Coastguard WorkerMake workload tensors using input and output binding information. 187*89c4ff92SAndroid Build Coastguard Worker```python 188*89c4ff92SAndroid Build Coastguard Worker# Load an image and create an inputTensor for inference. 189*89c4ff92SAndroid Build Coastguard Workerimg = imageio.imread('./image.png') 190*89c4ff92SAndroid Build Coastguard Workerinput_tensors = ann.make_input_tensors([input_binding_info], [img]) 191*89c4ff92SAndroid Build Coastguard Worker 192*89c4ff92SAndroid Build Coastguard Worker# Get output binding information for an output layer by using the layer name. 193*89c4ff92SAndroid Build Coastguard Workeroutput_binding_info = parser.GetNetworkOutputBindingInfo(0, 'model/output') 194*89c4ff92SAndroid Build Coastguard Workeroutput_tensors = ann.make_output_tensors([output_binding_info]) 195*89c4ff92SAndroid Build Coastguard Worker``` 196*89c4ff92SAndroid Build Coastguard Worker 197*89c4ff92SAndroid Build Coastguard WorkerPerform inference and get the results back into a numpy array. 198*89c4ff92SAndroid Build Coastguard Worker```python 199*89c4ff92SAndroid Build Coastguard Workerruntime.EnqueueWorkload(0, input_tensors, output_tensors) 200*89c4ff92SAndroid Build Coastguard Worker 201*89c4ff92SAndroid Build Coastguard Workerresults = ann.workload_tensors_to_ndarray(output_tensors) 202*89c4ff92SAndroid Build Coastguard Workerprint(results) 203*89c4ff92SAndroid Build Coastguard Worker``` 204*89c4ff92SAndroid Build Coastguard Worker 205*89c4ff92SAndroid Build Coastguard Worker#### Examples 206*89c4ff92SAndroid Build Coastguard Worker 207*89c4ff92SAndroid Build Coastguard WorkerTo further explore PyArmNN API there are several examples provided in the `/examples` folder for you to explore. 208*89c4ff92SAndroid Build Coastguard Worker 209*89c4ff92SAndroid Build Coastguard Worker##### Image Classification 210*89c4ff92SAndroid Build Coastguard Worker 211*89c4ff92SAndroid Build Coastguard WorkerThis sample application performs image classification on an image and outputs the <i>Top N</i> results, listing the classes and probabilities associated with the classified image. All resources are downloaded during execution, so if you do not have access to the internet, you may need to download these manually. 212*89c4ff92SAndroid Build Coastguard Worker 213*89c4ff92SAndroid Build Coastguard WorkerSample scripts are provided for performing image classification with TFLite and ONNX models with `tflite_mobilenetv1_quantized.py` and `onnx_mobilenetv2.py`. 214*89c4ff92SAndroid Build Coastguard Worker 215*89c4ff92SAndroid Build Coastguard Worker##### Object Detection 216*89c4ff92SAndroid Build Coastguard Worker 217*89c4ff92SAndroid Build Coastguard WorkerThis sample application guides the user and shows how to perform object detection using PyArmNN API. By taking a model and video file or camera feed as input, and running inference on each frame, we are able to interpret the output to draw bounding boxes around detected objects and overlay the corresponding labels and confidence scores. 218*89c4ff92SAndroid Build Coastguard Worker 219*89c4ff92SAndroid Build Coastguard WorkerSample scripts are provided for performing object detection from video file and video stream with `run_video_file.py` and `run_video_stream.py`. 220*89c4ff92SAndroid Build Coastguard Worker 221*89c4ff92SAndroid Build Coastguard Worker 222*89c4ff92SAndroid Build Coastguard Worker## Tox for automation 223*89c4ff92SAndroid Build Coastguard Worker 224*89c4ff92SAndroid Build Coastguard WorkerTo make things easier *tox* is available for automating individual tasks or running multiple commands at once such as generating wrappers, running unit tests using multiple python versions or generating documentation. To run it use: 225*89c4ff92SAndroid Build Coastguard Worker 226*89c4ff92SAndroid Build Coastguard Worker```bash 227*89c4ff92SAndroid Build Coastguard Worker$ tox <task_name> 228*89c4ff92SAndroid Build Coastguard Worker``` 229*89c4ff92SAndroid Build Coastguard Worker 230*89c4ff92SAndroid Build Coastguard WorkerSee *tox.ini* for the list of tasks. You may also modify it for your own purposes. To dive deeper into tox read through https://tox.readthedocs.io/en/latest/ 231*89c4ff92SAndroid Build Coastguard Worker 232*89c4ff92SAndroid Build Coastguard Worker## Running unit-tests 233*89c4ff92SAndroid Build Coastguard Worker 234*89c4ff92SAndroid Build Coastguard WorkerDownload resources required to run unit tests by executing the script in the scripts folder: 235*89c4ff92SAndroid Build Coastguard Worker 236*89c4ff92SAndroid Build Coastguard Worker``` 237*89c4ff92SAndroid Build Coastguard Worker$ python ./scripts/download_test_resources.py 238*89c4ff92SAndroid Build Coastguard Worker``` 239*89c4ff92SAndroid Build Coastguard Worker 240*89c4ff92SAndroid Build Coastguard WorkerThe script will download an archive from the Linaro server and extract it. A folder `test/testdata/shared` will be created. Execute `pytest` from the project root dir: 241*89c4ff92SAndroid Build Coastguard Worker```bash 242*89c4ff92SAndroid Build Coastguard Worker$ python -m pytest test/ -v 243*89c4ff92SAndroid Build Coastguard Worker``` 244*89c4ff92SAndroid Build Coastguard Workeror run tox which will do both: 245*89c4ff92SAndroid Build Coastguard Worker```bash 246*89c4ff92SAndroid Build Coastguard Worker$ tox 247*89c4ff92SAndroid Build Coastguard Worker``` 248