Notice:此次安裝是完整版本安裝包括優化器等,部署調用是基于Python環境,以及涉及到Intel NCS2神經網絡計算棒二代的部署
一、基本準備
1.Python3基本解釋器的準備,推薦Python3.8以上,如已有請忽略
2.硬體上至少得有一個USB3.0接口(有部署在 intel NCS2上需求的);以及一個CPU(Intel、AMD的都行)
二、環境搭建
Python環境配置
通過pip安裝可參考官方:
https://www.intel.cn/content/www/cn/zh/developer/tools/openvino-toolkit/download.html

https://www.intel.cn/content/www/cn/zh/developer/tools/openvino-toolkit/download.html
簡單而言就是:
打開cmd,cd /d 切換到一個自定義路徑,輸入指令:
步驟 1: 建立和激活虛拟環境(強烈建議使用虛拟環境,不然把Python系統環境搞得亂七八糟各種沖突的很麻煩)
python -m venv openvino_env
python -m venv openvino_env openvino_env\Scripts\activate
步驟 2: 将 pip 更新至最新版本
python -m pip install --upgrade pip
步驟 3: 下載下傳并安裝依賴庫
pip install openvino-dev[ONNX]==2022.2.0
完成以上步驟之後,通過pip list檢視一下是否安裝完全,但這個時候常常無法運作,因為系統驅動以及環境變量還未配置
系統驅動及環境變量配置
去Intel官方網站下載下傳對應版本的安裝包
https://www.intel.cn/content/www/cn/zh/developer/tools/openvino-toolkit/download.html

https://www.intel.cn/content/www/cn/zh/developer/tools/openvino-toolkit/download.html
選擇如下:
下載下傳完成後會得到一個壓縮包(個人覺得這是安裝最友善的一個版本),解壓到一個自定義路徑,如 C:\Program Files (x86)\Intel\OpenVINO
得到類似于下圖的目錄:
解壓完成後添加如下環境變量:
set "INTEL_OPENVINO_DIR=C:\Program Files (x86)\Intel\OpenVINO\"
set "OPENVINO_LIB_PATHS=
%INTEL_OPENVINO_DIR%\runtime\bin\intel64\Release;
%INTEL_OPENVINO_DIR%\runtime\bin\intel64\Debug;
%INTEL_OPENVINO_DIR%\runtime\3rdparty\tbb\bin;
%INTEL_OPENVINO_DIR%\runtime\3rdparty\hddl\bin;"
set "PATH=
%INTEL_OPENVINO_DIR%\runtime\bin\intel64\Release;
%INTEL_OPENVINO_DIR%\runtime\bin\intel64\Debug;
%INTEL_OPENVINO_DIR%\runtime\3rdparty\tbb\bin;
%INTEL_OPENVINO_DIR%\runtime\3rdparty\hddl\bin;
%INTEL_OPENVINO_DIR%\tools\compile_tool;"
配置完成後類似于:
配置完成後最好還是重新開機一下PC,然後打開cmd輸入cd C:\Program Files (x86)\Intel\OpenVINO,然後輸入setupvars.bat後執行,如下:
這一步主要是連接配接一下系統驅動與Python環境,主要是針對NCS2這樣的外置硬體,不然在運作時可能會出現NC_OUT_OF_MEMORY或者NC_ERROR這樣的錯誤(出現這樣的錯誤可能是因為驅動連接配接不上而逾時誤以為是記憶體過大而加載逾時,而另一種可能是使用的USB2.0接口導緻連接配接時間過長而逾時)
綜上,OpenVINO環境配置完畢
三、環境測試
安裝完成後激活虛拟環境,之後可用如下腳本進行測試:
from openvino.inference_engine import IECore
from openvino.runtime import Core
import numpy as np
if __name__ == '__main__':
# device
ie_core = IECore()
print('devices: ', ie_core.available_devices)
# run
core = Core()
net_small = core.compile_model(model='test.onnx', device_name="MYRIAD") # CPU GPU MYRIAD ...
output = net_small([np.array([1], dtype=np.float32)])[next(iter(net_small.outputs))]
print('small model work state: ', output)
print('over')
若運作正常則會輸出目前可用裝置以及測試模型輸出結果
測試模型可用如下腳本産生:
import torch
import torch.nn as nn
import torch.nn.functional as func
class ANN_Net(nn.Module):
def __init__(self, IO_num):
super(ANN_Net, self).__init__()
self.layer_o = nn.Linear(IO_num, 1)
def forward(self, x_in):
# In
x_out = func.relu(self.layer_o(x_in))
return x_out
if __name__ == '__main__':
x = torch.tensor([1]).to(torch.float32)
net = ANN_Net(1)
net.eval()
# onnx導出
torch.onnx.export(net, x, 'test.onnx',
verbose=True, keep_initializers_as_inputs=True, opset_version=11,
input_names=["input"], output_names=["output"])
print("finished exporting onnx ")
print(net(x))
四、關于使用OpenVINO優化模型
假如你已經有了一個訓練好的模型“test.onnx”,激活虛拟環境然後輸入指令
mo --input_model=test.onnx --model_name=test_fp16 --data_type=FP16 --enable_concat_optimization --progress
關于優化參數的解釋
--input_model INPUT_MODEL, -w INPUT_MODEL, -m INPUT_MODEL
Tensorflow*: a file with a pre-trained model (binary or text .pb file after freezing). Caffe*: a model proto file with model weights
Tensorflow *:具有預訓練模型的檔案(當機後的二進制或文本.pb檔案)。 Caffe *:具有模型權重的模型原型檔案
--model_name MODEL_NAME, -n MODEL_NAME
Model_name parameter passed to the final create_ir transform. This parameter is used to name a network in a generated IR and output .xml/.bin files.
将Model_name參數傳遞給最終的create_ir轉換。 此參數用于在生成的IR中命名網絡并輸出.xml / .bin檔案。
--output_dir OUTPUT_DIR, -o OUTPUT_DIR
Directory that stores the generated IR. By default, it is the directory from where the Model Optimizer is launched.
存儲生成的IR的目錄。 預設情況下,它是啟動模型優化器的目錄。
--input_shape INPUT_SHAPE
Input shape(s) that should be fed to an input node(s) of the model. Shape is defined as a comma-separated list of integer numbers enclosed in parentheses or square brackets, for example [1,3,227,227] or (1,227,227,3), where the order of dimensions depends on the framework input layout of the model. For example, [N,C,H,W] is used for Caffe* models and [N,H,W,C] for TensorFlow* models. Model Optimizer performs necessary transformations to convert the shape to the layout required by Inference Engine (N,C,H,W). The shape should not contain undefined dimensions (? or -1) and should fit the dimensions defined in the input operation of the graph. If there are multiple inputs in the model, --input_shape should contain definition of shape for each input separated by a comma, for example: [1,3,227,227],[2,4] for a model with two inputs with 4D and 2D shapes. Alternatively, specify shapes with the --input option.
應輸入模型的輸入節點的輸入形狀。 形狀定義為用逗号分隔的用括号或方括号括起來的整數清單,例如[1,3,227,227]或(1,227,227,3),其中尺寸順序取決于模型的架構輸入布局。 例如,[N,C,H,W]用于Caffe *模型,[N,H,W,C]用于TensorFlow *模型。 模型優化器執行必要的轉換,以将形狀轉換為推理引擎所需的布局(N,C,H,W)。 形狀不應包含未定義的尺寸(?或-1),并且應适合在圖形的輸入操作中定義的尺寸。 如果模型中有多個輸入,則--input_shape應包含每個輸入的形狀定義,并用逗号分隔,例如:[1,3,227,227],[2,4]對于具有兩個4D和2D形狀的輸入的模型 。 或者,使用--input選項指定形狀。
--scale SCALE, -s SCALE
All input values coming from original network inputs will be divided by this value. When a list of inputs is overridden by the --input parameter, this scale is not applied for any input that does not match with the original input of the model.
來自原始網絡輸入的所有輸入值都将被該值除。 當輸入清單被--input參數覆寫時,該比例不适用于與模型原始輸入不比對的任何輸入。
--reverse_input_channels
Switch the input channels order from RGB to BGR (or vice versa). Applied to original inputs of the model if and only if a number of channels equals 3. Applied after application of --mean_values and --scale_values options, so numbers in --mean_values and --scale_values go in the order of channels used in the original model.
将輸入通道順序從RGB切換到BGR(反之亦然)。 當且僅當通道數等于3時,才應用于模型的原始輸入。在應用--mean_values和--scale_values選項後應用,是以--mean_values和--scale_values中的數字按通道中使用的通道順序排列 原始模型。
--log_level {CRITICAL,ERROR,WARN,WARNING,INFO,DEBUG,NOTSET}
--input INPUT
Quoted list of comma-separated input nodes names with shapes, data types, and values for freezing. The shape and value are specified as space-separated lists. The data type of input node is specified in braces and can have one of the values: f64 (float64), f32 (float32), f16 (float16), i64 (int64), i32 (int32), u8 (uint8), boolean. For example, use the following format to set input port 0 of the node `node_name1` with the shape [3 4] as an input node and freeze output port 1 of the node `node_name2` with the value [20 15] of the int32 type and shape [2]: "0:node_name1[3 4],node_name2:1[2]{i32}->[20 15]".
用逗号分隔的輸入節點名稱(帶形狀,資料類型和當機值)的帶引号的清單。 形狀和值指定為以空格分隔的清單。 輸入節點的資料類型以大括号指定,并且可以具有以下值之一:f64(float64),f32(float32),f16(float16),i64(int64),i32(int32),u8(uint8),布爾值。 例如,使用以下格式将形狀為[3 4]的節點'node_name1'的輸入端口0設定為輸入節點,并當機節點int32的值[20 15]的節點`node_name2`的輸出端口1。 類型和形狀[2]:“ 0:node_name1 [3 4],node_name2:1 [2] {i32}-> [20 15]”。
--output OUTPUT
The name of the output operation of the model. For TensorFlow*, do not add :0 to this name.
模型的輸出操作的名稱。 對于TensorFlow *,請勿在該名稱上添加:0。
--mean_values MEAN_VALUES, -ms MEAN_VALUES
Mean values to be used for the input image per channel. Values to be provided in the (R,G,B) or [R,G,B] format. Can be defined for desired input of the model, for example: "--mean_values data[255,255,255],info[255,255,255]". The exact meaning and order of channels depend on how the original model was trained.
每個通道用于輸入圖像的平均值。 以(R,G,B)或[R,G,B]格式提供的值。 可以為模型的所需輸入定義,例如:“-mean_values data [255,255,255],info [255,255,255]”。 通道的确切含義和順序取決于原始模型的訓練方式。
--scale_values SCALE_VALUES
Scale values to be used for the input image per channel. Values are provided in the (R,G,B) or [R,G,B] format. Can be defined for desired input of the model, for example: "--scale_values data[255,255,255],info[255,255,255]". The exact meaning and order of channels depend on how the original model was trained.
每個通道用于輸入圖像的比例值。 值以(R,G,B)或[R,G,B]格式提供。 可以為模型的所需輸入定義,例如:“-scale_values data [255,255,255],info [255,255,255]”。 通道的确切含義和順序取決于原始模型的訓練方式。
--data_type {FP16,FP32,half,float}
Data type for all intermediate tensors and weights. If original model is in FP32 and --data_type=FP16 is specified, all model weights and biases are quantized to FP16.
所有中間張量和權重的資料類型。 如果原始模型位于FP32中,并且指定了--data_type = FP16,則所有模型權重和偏差都将量化為FP16。
--disable_fusing
Turn off fusing of linear operations to Convolution
關閉将線性運算與卷積的融合
--disable_resnet_optimization
Turn off resnet optimization
關閉Resnet優化
--finegrain_fusing FINEGRAIN_FUSING
Regex for layers/operations that won't be fused. Example: --finegrain_fusing Convolution1,.*Scale.*
正規表達式用于不會融合的層/操作。 示例:--finegrain_fusing卷積1,。* Scale。*
--disable_gfusing
Turn off fusing of grouped convolutions
關閉分組卷積的融合
--enable_concat_optimization
Turn on Concat optimization.
打開Concat優化。
--move_to_preprocess
Move mean values to IR preprocess section
将平均值移至IR預處理部分
--extensions EXTENSIONS
Directory or a comma separated list of directories with extensions. To disable all extensions including
those that are placed at the default location, pass an empty string.
目錄或以逗号分隔的帶有擴充名的目錄清單。 要禁用所有擴充名,包括放置在預設位置的擴充名,請傳遞一個空字元串。
--batch BATCH, -b BATCH
Input batch size
輸入批量
--version
Version of Model Optimizer
模型優化器的版本
--silent
Prevent any output messages except those that correspond to log level equals ERROR, that can be set with the following option: --log_level. By default,log level is already ERROR.
防止使用與以下日志選項對應的輸出消息(與日志級别對應的消息等于ERROR除外)進行設定:--log_level。 預設情況下,日志級别已為ERROR。
--freeze_placeholder_with_value fREEZE_PLACEHOLDER_WITH_VALUE Replaces input layer with constant node with provided value, for example: "node_name->True". It will be DEPRECATED in future releases. Use --input option to specify a value for freezing.
FREEZE_PLACEHOLDER_WITH_VALUE用具有提供值的恒定節點替換輸入層,例如:“ node_name-> True”。 在将來的版本中将不再使用。 使用--input選項指定當機值。
--generate_deprecated_IR_V7
Force to generate deprecated IR V7 with layers from old IR specification.
強制生成具有舊IR規範中的圖層的已棄用的IR V7。
--static_shape
Enables IR generation for fixed input shape (folding `ShapeOf` operations and shape-calculating sub-graphs to `Constant`). Changing model input shape using the Inference Engine API in runtime may fail for such an IR.
為固定的輸入形狀啟用IR生成(将“ ShapeOf”操作和形狀計算子圖折疊為“ Constant”)。 對于此類IR,在運作時使用Inference Engine API更改模型輸入形狀可能會失敗
--keep_shape_ops
The option is ignored. Expected behavior is enabled by default.
該選項被忽略。 預設情況下啟用預期行為。
--disable_weights_compression
Disable compression and store weights with original precision.
禁用壓縮并以原始精度存儲重量
--progress
Enable model conversion progress display.
啟用模型轉換進度顯示
--stream_output
Switch model conversion progress display to a multiline mode.
将模型轉換進度顯示切換到多行模式
--transformations_config
TRANSFORMATIONS_CONFIG Use the configuration file with transformations description.
TRANSFORMATIONS_CONFIG将配置檔案與轉換說明一起使用
最終将得到優化後的IR模型,包含三個檔案
這裡在NCS2上的部署代碼以NanoDet為例:
import cv2
import numpy as np
from post_process import (img_resize, use_NMS)
class OpenVINO_Forward:
def __init__(self, net_path):
if type(net_path) == str:
from openvino.runtime import Core
ie = Core()
use_device = "CPU" # CPU MYRIAD
self.net = ie.compile_model(model=net_path, device_name=use_device)
self.input_net = None
else:
from openvino.inference_engine import IECore
ie = IECore()
use_device = "MYRIAD" # CPU MYRIAD
IR_net = ie.read_network(model=net_path[0], weights=net_path[1])
self.net = ie.load_network(network=IR_net, device_name=use_device)
self.input_net = next(iter(self.net.input_info))
self.output_net = next(iter(self.net.outputs))
def forward(self, img, normalize=None, score_min=0.5):
img = np.ascontiguousarray(img)
if normalize is not None:
img = (img - normalize[0]) / normalize[1]
if self.input_net is None:
img = np.transpose(np.expand_dims(img, axis=0), (0, 3, 1, 2)).astype(np.float32)
output = self.net([img])[self.output_net]
else:
img = np.transpose(np.expand_dims(img, axis=0), (0, 3, 1, 2)).astype(np.float16)
output = self.net.infer(inputs={self.input_net: img})[self.output_net]
output = output[np.max(output[:, 4:], axis=1) >= score_min]
return output
class Options:
def __init__(self):
# ---base--- #
self.input_size = (320, 320) # w, h
self.classes_name = ['R3', 'B3', 'R0', 'B0', 'R4', 'B4', 'land']
self.score_min = 0.3
self.IoU_max = 0.35
data_mean = np.array([103.53, 116.28, 123.675])
data_std = np.array([57.375, 57.12, 58.395])
# ---auto--- #
self.normalize = [data_mean, data_std]
if __name__ == '__main__':
options = Options()
# 使用IR模型
openvino_model = OpenVINO_Forward(('nets/nanodet_fp16.xml', 'nets/nanodet_fp16.bin'))
# 使用ONNX模型
# openvino_model = OpenVINO_Forward('nets/nanodet.onnx')
frame = cv2.imread('test.jpg', 1)
frame = img_resize(frame, options.input_size, keep_ratio=True)
# 推理+解碼
predicts = openvino_model.forward(frame, options.normalize, score_min=options.score_min)
# 非極大值抑制
res_bbox = use_NMS(predicts, IoU_max=options.IoU_max)
# 顯示
for each_bbox in res_bbox:
# 畫框
cv2.rectangle(frame, tuple(each_bbox[:2].astype(np.int16)), tuple(each_bbox[2: 4].astype(np.int16)),
(255, 0, 0))
# 獲得最大機率類别索引
class_index = int(np.argmax(each_bbox[4:]))
# 獲得最大機率類别機率值
class_possible = str(np.round(each_bbox[4:][class_index], 4))
cv2.putText(frame, options.classes_name[class_index] + ' ' + class_possible,
tuple(each_bbox[:2].astype(np.int16)),
cv2.FONT_HERSHEY_SIMPLEX, 0.3, (22, 7, 207))
cv2.imshow('frame', frame)
cv2.waitKey()
Thanks for reading