Deploying deep-learning applications on edge devices helps to reduce power consumption by processing all the computation at edge itself.
In DL applications more than 70% memory and energy gets utilized for data movement, only less than 30% is actually required to compute.
Deploying deep-learning capabilities to edge devices can present security challenges.
For example, ensuring inference integrity or providing copyright protection of your deep-learning models
Good solution is to use cryptography to protect models as they are deployed and stored on edge devices.
- Once a model is optimized by the OpenVINO Model Optimizer, it's then deployed to target devices in the Intermediate Representation (IR) format.
- An optimized model is stored on an edge device and executed by the Inference Engine.
- To protect deep-learning models, we can encrypt an optimized model before deploying it to the edge device.
- The edge device should always keep the stored model protected and have the model decrypted in runtime only for use by the Inference Engine.
- The encrypted models are only decrypted within the sample application just before loading into the OpenVINO plugin.
Reference - https://docs.openvinotoolkit.org/latest/openvino_docs_IE_DG_protecting_model_guide.html
Fernet & Argon2
- The Fernet module is an implementation of AES-128 CBC (Cipher Block Chaining) mode algorithm.
- The Argon2 module is a KDF (Key Derivation Function) to generate a symmetric key to encrypt the model files and to protect/hash the user supplied password. Which will be the input for encryption and decryption
# Import python modules
import matplotlib.pyplot as plt
import os
import time
import sys
from qarpo.demoutils import *
print('Imported Python modules successfully.')
# Upgrade to the latest crypto liraries used
!pip3 install --upgrade cryptography
!pip3 install --upgrade argon2-cffi
1. Optimize & Convert the raw Model into OpenVINO IR format- Generate FP16/FP32 IR files
- Generate INT8 precision IR
#-----------------------------------------------------------------------------
# Download the raw model
#-----------------------------------------------------------------------------
!downloader.py --name mobilenet-ssd -o raw_models
!echo "\nAll files that were downloaded:"
!find ./raw_models
- mobilenet-ssd.prototxt - network architecture to run inference
- mobilenet-ssd.caffemodel - Binary containing trained weights
These files will need to be optimized using the Model Optimizer to create the necessary IR files. We will be running the inference model on different hardware devices which have different requirements on the precision of the model
For this model, we will run the Model Optimizer using the format:
The input arguments are as follows:
--input_model : The model's input .caffemodel file (the .prototxt with the same base name will be automatically found, otherwise the --input_proto argument would need to be specified)
--data_type : The model's data type and precision (e.g. FP16, FP32, INT8, etc.)
--output_dir : Output directory where to store the generated IR model files
--scale : Scaling (divide by) value to apply to input values
--mean_values : Mean values (one per channel) to be subtracted from input values before scaling
For converting our model, we will use the typical scaling value 256 and mean values [127, 127, 127] used with Caffe* models. The complete command will look like the following:
Run the following cell to use the Model Optimizer to Generate the FP16 and FP32 model IR files:
#-----------------------------------------------------------------------------
# Create FP16 IR files
#-----------------------------------------------------------------------------
!mo.py \
--input_model raw_models/public/mobilenet-ssd/mobilenet-ssd.caffemodel \
--data_type FP16 \
--output_dir models/mobilenet-ssd/FP16 \
--scale 256 \
--mean_values [127,127,127]
#-----------------------------------------------------------------------------
# Create FP32 IR files
#-----------------------------------------------------------------------------
!mo.py \
--input_model raw_models/public/mobilenet-ssd/mobilenet-ssd.caffemodel \
--data_type FP32 \
--output_dir models/mobilenet-ssd/FP32 \
--scale 256 \
--mean_values [127,127,127]
ResponseModel Optimizer arguments:
Common parameters:
- Path to the Input Model: /home/object-detection-python/raw_models/public/mobilenet-ssd/mobilenet-ssd.caffemodel
- Path for generated IR: /home/python/object-detection-python/models/mobilenet-ssd/FP16
- IR output name: mobilenet-ssd
- Log level: ERROR
- Batch: Not specified, inherited from the model
- Input layers: Not specified, inherited from the model
- Output layers: Not specified, inherited from the model
- Input shapes: Not specified, inherited from the model
- Mean values: [127,127,127]
- Scale values: Not specified
- Scale factor: 256.0
- Precision of IR: FP16
- Enable fusing: True
- Enable grouped convolutions fusing: True
- Move mean values to preprocess section: False
- Reverse input channels: False
Caffe specific parameters:
- Path to Python Caffe* parser generated from caffe.proto: /opt/intel/openvino-lts/deployment_tools/model_optimizer/mo/front/caffe/proto
- Enable resnet optimization: True
- Path to the Input prototxt: /home/python/object-detection-python/raw_models/public/mobilenet-ssd/mobilenet-ssd.prototxt
- Path to CustomLayersMapping.xml: Default
- Path to a mean file: Not specified
- Offsets for a mean file: Not specified
Model Optimizer version:
[ SUCCESS ] Generated IR version 10 model.
[ SUCCESS ] XML file: /home/python/object-detection-python/models/mobilenet-ssd/FP16/mobilenet-ssd.xml
[ SUCCESS ] BIN file: /home/python/object-detection-python/models/mobilenet-ssd/FP16/mobilenet-ssd.bin
[ SUCCESS ] Total execution time: 8.51 seconds.
[ SUCCESS ] Memory consumed: 187 MB.
It's been a while, check for a new version of Intel(R) Distribution of OpenVINO(TM) toolkit here https://software.intel.com/en-us/openvino-toolkit/choose-download?cid=&source=upgrade&content=2020_3_LTS or on the GitHub*
Model Optimizer arguments:
Common parameters:
- Path to the Input Model: /home/python/object-detection-python/raw_models/public/mobilenet-ssd/mobilenet-ssd.caffemodel
- Path for generated IR: /home/python/object-detection-python/models/mobilenet-ssd/FP32
- IR output name: mobilenet-ssd
- Log level: ERROR
- Batch: Not specified, inherited from the model
- Input layers: Not specified, inherited from the model
- Output layers: Not specified, inherited from the model
- Input shapes: Not specified, inherited from the model
- Mean values: [127,127,127]
- Scale values: Not specified
- Scale factor: 256.0
- Precision of IR: FP32
- Enable fusing: True
- Enable grouped convolutions fusing: True
- Move mean values to preprocess section: False
- Reverse input channels: False
Caffe specific parameters:
- Path to Python Caffe* parser generated from caffe.proto: /opt/intel/openvino-lts/deployment_tools/model_optimizer/mo/front/caffe/proto
- Enable resnet optimization: True
- Path to the Input prototxt: /home/python/object-detection-python/raw_models/public/mobilenet-ssd/mobilenet-ssd.prototxt
- Path to CustomLayersMapping.xml: Default
- Path to a mean file: Not specified
- Offsets for a mean file: Not specified
Model Optimizer version:
[ SUCCESS ] Generated IR version 10 model.
[ SUCCESS ] XML file: /home/python/object-detection-python/models/mobilenet-ssd/FP32/mobilenet-ssd.xml
[ SUCCESS ] BIN file: /home/python/object-detection-python/models/mobilenet-ssd/FP32/mobilenet-ssd.bin
[ SUCCESS ] Total execution time: 8.62 seconds.
[ SUCCESS ] Memory consumed: 188 MB.
It's been a while, check for a new version of Intel(R) Distribution of OpenVINO(TM) toolkit here https://software.intel.com/en-us/openvino-toolkit/choose-download?cid=&source=upgrade&content=2020_3_LTS or on the GitHub*
\nAll IR files that were created:
./models/mobilenet-ssd/FP32/mobilenet-ssd.bin
./models/mobilenet-ssd/FP32/mobilenet-ssd.xml
./models/mobilenet-ssd/FP16/mobilenet-ssd.bin
./models/mobilenet-ssd/FP16/mobilenet-ssd.xml
2. Model EncryptionSet the password needed to encrypt the model files
import getpass
pw = getpass.getpass()
!echo "[ok] password is set."
2.2. Encrypt the ModelThe sample uses Fernet for encrypting the file, using the encryption key generated with Argon2 which is derived from the supplied password.
The same password will be during the decryption
import base64
from cryptography.fernet import Fernet
import argon2, binascii
def encrypt(password, argon2_parameters, in_file, out_file):
hasher = argon2.PasswordHasher(time_cost=argon2_parameters.time_cost, \
memory_cost=argon2_parameters.memory_cost, \
parallelism=argon2_parameters.parallelism, \
hash_len=argon2_parameters.hash_len, \
salt_len=argon2_parameters.salt_len)
pw_hash = hasher.hash(pw)
salt = pw_hash.split("$")[-2]
raw_hash = argon2.low_level.hash_secret_raw(time_cost=argon2_parameters.time_cost, \
memory_cost=argon2_parameters.memory_cost, \
parallelism=argon2_parameters.parallelism, \
hash_len=argon2_parameters.hash_len, \
secret=bytes(password, "utf_16_le"), \
salt=bytes(salt, "utf_16_le"), \
type=argon2_parameters.type)
key = base64.urlsafe_b64encode(raw_hash)
fernet = Fernet(key)
with open(in_file, 'rb') as f_in, open(out_file, 'wb') as f_out:
data = f_in.read()
enc_data = fernet.encrypt(data)
pw_hash = pw_hash + '\n'
f_out.write(bytes(pw_hash, "utf-8"))
f_out.write(enc_data)
if __name__ == '__main__':
xml_file = "models/mobilenet-ssd/FP32/mobilenet-ssd.xml"
bin_file = "models/mobilenet-ssd/FP32/mobilenet-ssd.bin"
encrypt_xml_file = "models/mobilenet-ssd/FP32/mobilenet-ssd-encrypt.xml"
encrypt_bin_file = "models/mobilenet-ssd/FP32/mobilenet-ssd-encrypt.bin"
p = argon2.Parameters(type=argon2.low_level.Type.ID, \
version=19, \
salt_len=16, \
hash_len=32, \
time_cost=16, \
memory_cost=2**20, \
parallelism=8)
encrypt(pw, p, xml_file, encrypt_xml_file)
print ("[ok] .xml encrypted")
encrypt(pw, p, bin_file, encrypt_bin_file)
print ("[ok] .bin encrypted")
2.3 Encrypted OpenVINO IR!ls -l models/mobilenet-ssd/FP16/
!echo "[ok] encrypt .xml&.bin file"
[ok] .xml encrypted
[ok] .bin encrypted
total 53148
-rw------- 1 u84412 u84412 23133788 Aug 27 03:53 mobilenet-ssd.bin
-rw------- 1 u84412 u84412 30845233 Aug 27 03:55 mobilenet-ssd-encrypt.bin
-rw------- 1 u84412 u84412 237277 Aug 27 03:54 mobilenet-ssd-encrypt.xml
-rw------- 1 u84412 u84412 15885 Aug 27 03:53 mobilenet-ssd.mapping
-rw------- 1 u84412 u84412 177808 Aug 27 03:53 mobilenet-ssd.xml
[ok] encrypt .xml&.bin file
3. Decrypt Model and Run inferenceThe OpenVINO Inference Engine requires model decryption before loading.
Allocate a temporary memory block for model decryption,
and use IECoremethods to load the model from memory buffer.
Read model files and decrypt them into temporary memory block
dec_xml = decrypt(password, model_xml)
dec_bin = decrypt(password, model_bin)
Use IECore.read_network() to set model representations and weights respectively.
net = IECore.read_network(model=dec_xml, weights=dec_bin, init_from_buffer=True)
decrypt and loading the model IR files, which could be found in object_detection.py
# IR files decryption function
# input: password and encrypted file path
# output: buffer containing decrypted file content
def decrypt(password, in_file):
with open(in_file, 'r') as f:
pw_hash = f.readline()[:-1]
p = argon2.extract_parameters(pw_hash)
hasher = argon2.PasswordHasher(time_cost=p.time_cost, \
memory_cost=p.memory_cost, \
parallelism=p.parallelism, \
hash_len=p.hash_len, \
salt_len=p.salt_len)
try:
hasher.verify(pw_hash, password)
log.info("Argon2 verify: true")
except:
log.error("Argon2 verify: false, check password")
exit()
salt = pw_hash.split("$")[-2]
raw_hash = argon2.low_level.hash_secret_raw(time_cost=p.time_cost, \
memory_cost=p.memory_cost, \
parallelism=p.parallelism, \
hash_len=p.hash_len, \
secret=bytes(password, "utf_16_le"), \
salt=bytes(salt, "utf_16_le"), \
type=p.type)
key = base64.urlsafe_b64encode(raw_hash)
fernet = Fernet(key)
dec_data = b''
with open(in_file, 'rb') as f_in:
enc_data = f_in.readlines()[1]
try:
dec_data = fernet.decrypt(enc_data)
except:
log.error("decryption faile")
return dec_data
#------------------------------------------------------------------------
...
# decrypting and loading the model IR files
dec_xml = decrypt(pw, model_xml)
dec_bin = decrypt(pw, model_bin)
net = ie.read_network(model=dec_xml, weights=dec_bin, init_from_buffer=True)
...
4. Inference executionObject_detection -h
[-h] -m MODEL -i INPUT [-ce CPU_EXTENSION] [-d DEVICE]
[-nireq NUMBER_INFER_REQUESTS] [-s] [-l LABELS]
[-pt PROB_THRESHOLD] -o OUTPUT_DIR [-pw PASSWORD]
optional arguments:
-h, --help show this help message and exit .
-m MODEL, --model MODEL Path to an .xml file with a trained model.
-i INPUT, --input INPUT Path to video file or image. 'cam' for capturing
videostream from camera.
-ce CPU_EXTENSION, --cpu_extension CPU_EXTENSION MKLDNN-targeted custom layers.Absolute path to ashared library with the kernel implementation.
-d DEVICE, --device DEVICE Specify the target device to infer on; CPU, GPU,
FPGA,MYRIAD, or HDDL is acceptable.Demo will look for a suitable plugin for specified device (CPU by default).
-nireq NUMBER_INFER_REQUESTS, --number_infer_requests NUMBER_INFER_REQUESTS
Number of parallel inference requests (default is 2).
-s, --show Show preview to the user.
-pt PROB_THRESHOLD, --prob_threshold PROB_THRESHOLD Probability threshold for detection filtering.
-o OUTPUT_DIR, --output_dir OUTPUT_DIR Location to store the results of the
processing .
-pw PASSWORD, --password PASSWORD Password used to decrypt .xml&.bin file .
5. DL model5.1. Model ParametersHere is the steps to enable SSH in Raspberry Pi with Mobile Hotspot/Wifi.
6.1.1. Download Required OS and softwares- Download Raspberry Pi OS from https://www.raspberrypi.org/downloads/
- Download and install SD card formatter from https://www.sdcard.org/downloads/formatter/
- Download and install Etcher from - https://www.balena.io/etcher/
- Download and install from https://www.realvnc.com/en/connect/download/viewer/
- Format SD card using SD card formatter
- Flash Raspberry Pi OS into SD card by selecting previously downloaded pi OS image and SD card volume using Etcher
- Unplug and re-insert the SD card reader in machine(OS - ubuntu, MacOs), open SD card volume. Mostly, by default you can find folder name boot, in my case I got "recovery" as a boot folder name.
Some files need to be added before inserting SD card into Raspberry Pi.
- SSH access is disabled by default in model 4. To enable ssh, create an empty file named
ssh
in SD card folder - Create a file named wpa_supplicant.conf. Paste the following piece of code in it. And update Hotspot/wifi name and password in respective fields
country=IN
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="mobile_hotspot_name or wifi name"
psk="mobile_hotspot_passwd or wifi password"
}
6.1.4. Find IP address- Connect Computer with Mobile Hotspot/Wifi
- Install any preferred IP scanner to find IP
- or Open HotSpot setting in your Android/iOS mobile, in that you can see connected devices, from that you can get Raspberry Pi IP and there are other methods like nmap also there.
- Insert SD card into pi board. Connect usb to c-type cable from your Computer to power up the board.
- Open terminal, replace ip address of your raspberry pi.
ssh pi@raspberrypi-ip-address
- You will be prompted for the password, default pi password is - raspberry
- In the pi terminal run sudo raspi-config and select option 5. Interfacing Options
- In that select option 3. VNC to enable Graphic remote access to Pi
- Create "New connection", enter Raspberry Pi IP address in "VNC server field" and connect.
- Select "continue", Finally you will get GUI access to Raspberry Pi
Link - https://docs.openvinotoolkit.org/2020.1/_docs_install_guides_installing_openvino_raspbian.html
sudo apt install cmake
sudo mkdir -p /opt/intel/openvino
sudo tar -xf l_openvino_toolkit_runtime_raspbian_p_<version>.tgz --strip 1 -C /opt/intel/openvino
source /opt/intel/openvino/bin/setupvars.sh
sudo usermod -a -G users "$(whoami)"
sh /opt/intel/openvino/install_dependencies/install_NCS_udev_rules.sh
7. Movidius - Neural compute Stick2Neural Compute Stick can be connected with these hosts,
- Ubuntu
- MacOS
- Raspberry Pi
Step1: Install OpenVINO on Pi
Step2: Plug NCS2 and verify device detection
Step3: Initialize OpenVINO
Step4: Clone given github and execute this command
movidius plugin enables this NCS 2 execution
python3 object_detection.py \
-m <path to model>/model.xml \
-i input/input_video.mov \
-d HETERO: MYRIAD, CPU \
-pw "decryption password"
7.2. Defining and Configuring the Multi-Device pluginFollowing the OpenVINO notions of "devices", the Multi-Device has a "MULTI" name. The only configuration option for the Multi-Device plugin is a prioritized list of devices to use:
the explicit configuration to use both would be "MULTI:MYRIAD.1.2-ma2480, MYRIAD.1.4-ma2480". Accordingly, the code that loops over all available devices of "MYRIAD" type only is below:
InferenceEngine::Core ie;
auto cnnNetwork = ie.ReadNetwork("sample.xml");
std::string allDevices = "MULTI:";
std::vector<std::string> myriadDevices = ie.GetMetric("MYRIAD", METRIC_KEY(AVAILABLE_DEVICES));
for (size_t i = 0; i < myriadDevices.size(); ++i) {
allDevices += std::string("MYRIAD.")
+ myriadDevices[i]
+ std::string(i < (myriadDevices.size() -1) ? "," : "");
}
InferenceEngine::ExecutableNetwork exeNetwork = ie.LoadNetwork(cnnNetwork, allDevices, {});
List device
Device: MYRIAD.1.2-ma2480
Device: MYRIAD.1.4-ma2480
8. Benchmark: TFLite VS OpenVINOFrameworks tested:Performance comparison taken for object detection,TFLite 3 fps with Raspberry Pi & OpenVINO 27 fps with Raspberry Pi + NCS2 combination
9X improvement with OpenVINO + Raspberry pi + NCS2 than TFLite
Power consumption of Neural compute stick
NCS 2 - Runtime Power consumption is less than 2W
1. Connected over wifi,
2. Input support - Offline/Online videos/Images, RTSP stream and Pi camera module
Can be configured easily with different computer vision Applications
Here is list of tested openvino Pre-trained models
person-attributes-recognition-crossroad
license-plate-recognition-barrier
Person- reidentification -retail
landmarks-regression-retail
person-detection-action-recognition
road-segmentation-adas
Person-detection-retail
vehicle-detection-adas
human-pose-estimation
Vehicle-attributes-recognition-barrier
face-detection- adas
Vehicle-license-plate-detection-barrier
face-detection- adas
image-retrieval
age-gender-recognition-retail
pedestrian-and-vehicle-detector-adas
emotions-recognition-retail
pedestrian-detection-adas
facial-landmarks-35-adas
person-vehicle-bike-detection-crossroad
head-pose-estimation-adas
handwritten-japanese-recognition
gaze-estimation-adas
- Reducing data movement by processing compute at Edge. Data movement is key bottleneck
- In Deep Learning models, more than 70% memory and energy gets utilized for data movement, only less than 30% is actually required for compute.
- Reducing power consumption with Egde compute, can eliminate unnecessary data movement.
- Power consumption of Neural Compute Stick is less than 2W
- contributing to environmental CO2 footprint reduction
Comments