Deep Learning Prediction with ARM Compute Using codegen
This example shows how to use codegen
to generate code for a logo classification application that uses deep learning on ARM® processors. The logo classification application uses the dlnetwork
object to perform logo recognition from images. The generated code takes advantage of the ARM Compute library for computer vision and machine learning.
Third-Party Prerequisites
ARM processor that supports the NEON extension
Open Source Computer Vision Library (OpenCV) v3.1
Environment variables for ARM Compute and OpenCV libraries
The ARM Compute library version that this example uses might not be the latest version that code generation supports. For supported versions of libraries and for information about setting up environment variables, see Prerequisites for Deep Learning with MATLAB Coder (MATLAB Coder).
This example is supported on Linux® and Windows® platforms and not supported for MATLAB® Online™.
Get the Pretrained SeriesNetwork
Download the pretrained LogoNet
network and save it as logonet.mat
, if it does not exist. The network was developed in MATLAB and its architecture is similar to that of AlexNet. This network can recognize 32 logos under various lighting conditions and camera angles.
net = getLogonet();
Convert the SeriesNetwork
network object to a dlnetwork
object and save the network to a MAT file.
dlconvnet = dag2dlnetwork(net); save dlLogoNet.mat dlconvnet
The network contains 22 layers including convolution, fully connected, and the classification output layers. To view the network architecture, use the analyzeNetwork
function.
analyzeNetwork(dlconvnet)
Set Environment Variables
On the ARM target hardware, make sure that ARM_COMPUTELIB is set and that LD_LIBRARY_PATH contains the path to the ARM Compute Library folder.
logonet_predict Entry-Point Function
The logonet_predict.m
entry-point function takes an image input and performs prediction on the image by using the deep learning network saved in the dlLogoNet.mat
file. The function loads the network object from dlLogoNet.mat
into a persistent variable dlLogonet
and reuses the persistent variable on subsequent prediction calls. A dlarray object is created within the function, input and output to the function are of primitive datatypes.
type logonet_predict
function out = logonet_predict(in) %#codegen % Copyright 2017-2023 The MathWorks, Inc. % A persistent object dlLogonet is used to load the network object. At the % first call to this function, the persistent object is constructed and % setup. When the function is called subsequent times, the same object is % reused to call predict on inputs, thus avoiding reconstructing and % reloading the network object. dlIn = dlarray(in, 'SSC'); persistent dlLogonet; if isempty(dlLogonet) dlLogonet = coder.loadDeepLearningNetwork('dlLogoNet.mat','dlLogonet'); end dlOut = predict(dlLogonet, dlIn); out = extractdata(dlOut); end
Generate Source C++ Code
When you generate code targeting an ARM-based device and do not use a hardware support package, create a configuration object for a library. Do not create a configuration object for an executable program.
Create a configuration object for a Static Library. Set the target language to C++ and generation of code only.
cfg = coder.config('lib'); cfg.TargetLang = 'C++'; cfg.GenCodeOnly = true;
Create a coder.ARMNEONConfig
object. Specify the library version and the architecture of the target ARM processor. For example, suppose that the target board is a HiKey/Rock960 board with ARMv8 architecture and ARM Compute Library version 20.02.1.
dlcfg = coder.DeepLearningConfig('arm-compute'); dlcfg.ArmComputeVersion = '20.02.1'; dlcfg.ArmArchitecture = 'armv8';
Attach the deep learning configuration object to the code generation configuration object. Use the codegen command to generate source code.
cfg.DeepLearningConfig = dlcfg; codegen -config cfg logonet_predict -args {ones(227, 227, 3, 'single')} -d arm_compute
Code generation successful.
The code is generated in the arm_compute
folder in the current working folder on the host computer.
Generate the Zip File Using the packNGo
Function
The packNGo function packages all relevant files in a compressed zip file.
zipFileName = 'arm_compute.zip'; bInfo = load(fullfile('arm_compute','buildInfo.mat')); packNGo(bInfo.buildInfo, {'fileName', zipFileName,'minimalHeaders', false, 'ignoreFileMissing',true});
Copy the Generated Zip File to the Target Hardware
Copy the zip file and extract into a folder. Remove the Zip file from the target hardware.
In the following commands, replace:
password
with your passwordusername
with your user nametargetname
with the name of your devicetargetloc
with the destination folder for the files
Run these commands to copy and extract zip file from Linux.
if isunix, system(['sshpass -p password scp -r ' fullfile(pwd,zipFileName) ' username@targetname:targetloc/']), end if isunix, system('sshpass -p password ssh username@targetname "if [ -d targetloc/arm_compute ]; then rm -rf targetloc/arm_compute; fi"'), end if isunix, system(['sshpass -p password ssh username@targetname "unzip targetloc/' zipFileName ' -d targetloc/arm_compute"']), end if isunix, system(['sshpass -p password ssh username@targetname "rm -rf targetloc' zipFileName '"']), end
Run these commands to copy and extract zip file from Windows.
if ispc, system(['pscp.exe -pw password -r ' fullfile(pwd,zipFileName) ' username@targetname:targetloc/']), end if ispc, system('plink.exe -l username -pw password targetname "if [ -d targetloc/arm_compute ]; then rm -rf targetloc/arm_compute; fi"'), end if ispc, system(['plink.exe -l username -pw password targetname "unzip targetloc/' zipFileName ' -d targetloc/arm_compute"']), end if ispc, system(['plink.exe -l username -pw password targetname "rm -rf targetloc' zipFileName '"']), end
Copy Example Files to the Target Hardware
Copy these supporting files from the host computer to the target hardware:
Input image,
coderdemo_google.png
Makefile for generating the library,
logonet_predict_rtw.mk
Makefile for building the executable program,
makefile_arm_logo.mk
Synset dictionary,
synsetWordsLogoDet.txt
In the following commands, replace:
password
with your passwordusername
with your user nametargetname
with the name of your devicetargetloc
with the destination folder for the files
Perform the steps below to copy all the required files when running from Linux.
if isunix, system('sshpass -p password scp logonet_predict_rtw.mk username@targetname:targetloc/arm_compute/'), end if isunix, system('sshpass -p password scp coderdemo_google.png username@targetname:targetloc/arm_compute/'), end if isunix, system('sshpass -p password scp makefile_arm_logo.mk username@targetname:targetloc/arm_compute/'), end if isunix, system('sshpass -p password scp synsetWordsLogoDet.txt username@targetname:targetloc/arm_compute/'), end
Perform the steps below to copy all the required files when running from Windows.
if ispc, system('pscp.exe -pw password logonet_predict_rtw.mk username@targetname:targetloc/arm_compute/'), end if ispc, system('pscp.exe -pw password coderdemo_google.png username@targetname:targetloc/arm_compute/'), end if ispc, system('pscp.exe -pw password makefile_arm_logo.mk username@targetname:targetloc/arm_compute/'), end if ispc, system('pscp.exe -pw password synsetWordsLogoDet.txt username@targetname:targetloc/arm_compute/'), end
Build the Library on the Target Hardware
To build the library on the target hardware, execute the generated makefile on the ARM hardware.
Make sure that you set the environment variables ARM_COMPUTELIB and LD_LIBRARY_PATH on the target hardware. The ARM_ARCH variable is used in the Makefile to pass compiler flags based on Arm Architecture. ARM_VER variable is used in the Makefile to compile the code based on Arm Compute Version. Replace the hardware credentials and paths in these commands similar to previous section.
Perform the below steps to build the library from Linux.
if isunix, system('sshpass -p password scp main_arm_logo.cpp username@targetname:targetloc/arm_compute/'), end if isunix, system(['sshpass -p password ssh username@targetname "make -C targetloc/arm_compute/ -f logonet_predict_rtw.mk ARM_ARCH=' dlcfg.ArmArchitecture ' ARM_VER=' dlcfg.ArmComputeVersion ' "']), end
Perform the below steps to build the library from windows.
if ispc, system('pscp.exe -pw password main_arm_logo.cpp username@targetname:targetloc/arm_compute/'), end if ispc, system(['plink.exe -l username -pw password targetname "make -C targetloc/arm_compute/ -f logonet_predict_rtw.mk ARM_ARCH=' dlcfg.ArmArchitecture ' ARM_VER=' dlcfg.ArmComputeVersion ' "']), end
Create Executable from the Library on the Target Hardware
Build the library with the source main wrapper file to create the executable. main_arm_logo.cpp
is the C++ main wrapper file which invokes the logonet_predict
function.
Run the below command to create the executable from Linux.
if isunix, system('sshpass -p password ssh username@targetname "make -C targetloc/arm_compute/ -f makefile_arm_logo.mk targetDirName=targetloc/arm_compute"'), end
Run the below command to create the executable from Windows.
if ispc, system('plink.exe -l username -pw password targetname "make -C targetloc/arm_compute/ -f makefile_arm_logo.mk targetDirName=targetloc/arm_compute"'), end
Run the Executable on the Target Hardware
Run the executable from Linux using below command.
if isunix, system('sshpass -p password ssh username@targetname "cd targetloc/arm_compute/; ./logonet coderdemo_google.png"'), end
Run the executable from Windows using below command.
if ispc, system('plink.exe -l username -pw password targetname "cd targetloc/arm_compute/; ./logonet coderdemo_google.png"'), end
Top 5 Predictions: ----------------------------- 99.992% google 0.003% corona 0.003% singha 0.001% esso 0.000% fedex