添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

OpenVINO分为转换与部署两个部分,如下图所示

在转换步中,需要将输入模型序列化后传入OpenVINO的 MO Model Optimizer工具对模型进行优化,以得到 IR
Intermediate Representation中间表示,详细的内部行为可以参考 Model Optimizer Developer Guide 。接着,在部署步中,我们使用OpenVINO提供的Python或者CPP的api,进行编程以达到我们想要的结果:1) 载入ir文件, 2) 建立 ie Inference Engine推理引擎, 3) 生成执行对象ExecutableNetwork, 载入不同的plugin,以支持特定的硬件(CPU、GPU等等),详细行为可参考 Inference Engine Developer Guide

对于转换步,针对"输入模型序列化"我就产生了疑问,OpenVINO所使用的序列化后进行ir转换的模型,它是一个类似静态图的东西,序列化后我再转换,那岂不就是我只能支持输入静态分辨率了?要使用OpenVINO化的模型进行推理,任意输入就得按照序列化时的分辨率来推理,岂不是很僵硬。难道,OpenVINO的推理,就得先插值,再推理,最后再插值回原分辨率?

这里就直接给结论了,OpenVINO是支持动态输入的,并且在它的手册里,也有相应的段落 Using Shape Inference ,乍看起来很简单,但实则暗藏坑点,这里我也直接给出坑点来,CPP api是无法全面支持OpenVINO reshape操作的:

  1. Python api 全面支持reshape操作,不会出错
  2. CPP api 某些简单网络支持,我推测还是scale的精度问题,参考我之前的日志 PyTorch转ONNX之F.interpolate ,从4到9,python搞得定,cpp估计就搞不定了,例如就会报如下的错,也是网络内部的upsample的问题,所以可以在2) 建立ie引擎的时候,加入resize层,也就是在ir外部添加一个处理,而不是reshape整个ir
    在这里插入图片描述

那么,下面就是两部分的详细说明

Python api

由于Python不像CPP,在精度和内存分配上,我们都不需要担心,所以完全可以使用OpenVINO自带的reshape操作,将整个ir调整到适合的输入分辨率。

这里需要注意两点,一是在使用mo工具进行ir转换的时候,需要使用 --keep_shape_ops ,二是在部署的时候,需要在"3) 生成ExecutableNetwork对象"前使用reshape。

一、使用mo转换ir

--keep_shape_ops
                    [ Experimental feature ] Enables `Shape` operation
                    with all children keeping. This feature makes model
                    reshapable in Inference Engine

详细地,可以参考When to Specify --keep_shape_ops Command Line Parameter,mo工具会保留内部的分辨率变化的图结构,实话说这部分保留了什么样的图结构,我不清楚,我猜是像onnx那样的scale值,onnx是通过scale值来计算输入与输出的分辨率大小,有可能,--keep_shape_ops取消了原本scale的const类型?

二、使用python api进行推理

这里我给一个示例代码,这里也是修改自OpenVINO提供的deployment_tools/inference_engine/samples/python里面的,我把注释和提示信息打印了出来,方便大家理解。

# model config
model_xml = 'your_model.xml'
model_bin = 'your_model.bin'
# Read IR
print("Creating Inference Engine...")
ie = IECore()
print("Loading network files:\n\t{}\n\t{}".format(model_xml, model_bin))
net = ie.read_network(model=model_xml, weights=model_bin)
# Check params in IR
# 检查IR模型是否是支持CPU硬件的
supported_layers = ie.query_network(net, "CPU")
not_supported_layers = [l for l in net.layers.keys() if l not in supported_layers]
if len(not_supported_layers) != 0:
    print("Following layers are not supported by the plugin for specified device {}:\n {}".
              format('CPU', ', '.join(not_supported_layers)))
    print("Please try to specify cpu extensions library path in sample's command line parameters using -l "
          "or --cpu_extension command line argument")
    sys.exit(1)
# 检查输入层的维度,这里说明是一个输入
assert len(net.inputs.keys()) == 1, "Sample supports only 1 input topologies -> {}".format(len(net.inputs.keys()))
# xml里面“注册”的输入的名字
required_input_keys = {'input'}
assert required_input_keys == set(net.inputs.keys()), \
    'Demo supports only topologies with the following input keys: {}'.format(', '.join(required_input_keys))
# 检查输出层的维度,这里有两个输出
assert len(net.outputs) == 2, "Sample supports only single output topologies"
# xml里面“注册”的输出的名字
required_output_keys = {'boxes', 'scores'}
assert required_output_keys.issubset(net.outputs.keys()), \
    'Demo supports only topologies with the following output keys: {}'.format(', '.join(required_output_keys))
# Read and pre-process input images
n, c, h, w = net.inputs['input'].shape
print("input_blob NxCxHxW is {}x{}x{}x{}".format(n, c, h, w))
# Reshape IR
# 读入输入图像的分辨率
input_size = cv2.imread("your_input_image.png").shape[:-1]
net.reshape({'input': (1, 3, input_size[0], input_size[1])})
n, c, h, w = net.inputs['input'].shape
print("input_blob NxCxHxW is resized to {}x{}x{}x{}".format(n, c, h, w))
# Loading model to the plugin
# 生成执行对象ExecutableNetwork
print("Loading model to the plugin")
exec_net = ie.load_network(network=net, device_name='CPU')
# Inference
print("Starting inference in synchronous mode")
for j in range(len(img_list)):
    img_path = img_list[j]
    ori_img  = cv2.imread(img_path)
    img = cv2.cvtColor(ori_img, cv2.COLOR_BGR2RGB)
    img = np.array(img, dtype=np.float32)
    img = img.transpose((2, 0, 1))  # Change data layout from HWC to CHW
    img = img[np.newaxis, :, :, :]  # 整成1CHW
    # Start sync inference
    print('[{}/{}]'.format(j, len(img_list)))
    res = exec_net.infer(inputs={'input': img})
    # Get results
    boxes  = res['boxes']
    scores = res['scores']
    # Post-processing

这里说明下“注册”是个啥意思,就是输入输出层的名字,实际上静态图里面,各层都是有类似“conv35”——“层类型-层的id”这样的名字,如果在IR转换的时候不规定,就是默认“conv35”的名称,规定层的名称,就是“注册”,我感觉这样来形容更加贴切一点。

CPP api

一、使用CPP api进行推理

模型转换那里是一样的,因此就不再赘述。

按理说,流程应该与“Python api推理”的流程是一致的,在文档Using Shape Inference的Usage of Reshape Method中提到CPP的流程如下所示:

InferenceEngine::Core core;
// ------------- 0. Read IR and image ----------------------------------------------
CNNNetwork network = core.ReadNetwork("path/to/IR/xml");
cv::Mat image = cv::imread("path/to/image");
// ---------------------------------------------------------------------------------
// ------------- 1. Collect the map of input names and shapes from IR---------------
auto input_shapes = network.getInputShapes();
// ---------------------------------------------------------------------------------
// ------------- 2. Set new input shapes -------------------------------------------
std::string input_name;
SizeVector input_shape;
std::tie(input_name, input_shape) = *input_shapes.begin(); // let's consider first input only
input_shape[0] = batch_size; // set batch size to the first input dimension
input_shape[2] = image.rows; // changes input height to the image one
input_shape[3] = image.cols; // changes input width to the image one
input_shapes[input_name] = input_shape;
// ---------------------------------------------------------------------------------
// ------------- 3. Call reshape ---------------------------------------------------
network.reshape(input_shapes);
// ---------------------------------------------------------------------------------
...
// ------------- 4. Loading model to the device ------------------------------------
std::string device = "CPU";
ExecutableNetwork executable_network = core.LoadNetwork(network, device);
// ---------------------------------------------------------------------------------

虽然会报之前讲到的错,因此我觉得这条reshape路是不容易走通的,那么是不是就卡关了呢?实际上是有解的,OpenVINO提供在"3) 生成ExecutableNetwork对象"前添加一个类似resize层的东西,这样就不会变动IR结构,而且使用OpenVINO提供的内建的resize操作,比自己在输入OpenVINO前进行自己的resize操作,我感觉应该是要快一点,如果画成图的话,就如下图所示,我们可以使用OpenVINO优化后的resize操作。

using namespace InferenceEngine;
Core ie;
string cnnNetworkXmlPath;
// ------------- 0. Read IR ----------------------------------------------
// 读取xml与bin
// ie默认读入与xml文件同名同路径的bin文件
// 例如,你的xml路径为/data/your_model.xml,那么ie会默认读取/data/your_model.bin
auto cnnNetwork = ie.ReadNetwork(cnnNetworkXmlPath);
// -----------------------------------------------------------------------
// ------------- 1. Collect the map of input names and shapes from IR-----
// 获取网络的输入信息
InputsDataMap inputInfo(cnnNetwork.getInputsInfo());
for (const auto & inputInfoItem : inputInfo) 
    if (inputInfoItem.second->getTensorDesc().getDims().size() == 4) 
        // 确保输入一定是4维,包含N、C、H、W
        imageInputName = inputInfoItem.first;
        // 设置输入精度为uint8,这样CPU占用要小一些
        inputInfoItem.second->setPrecision(Precision::U8);
        // 设置输入的维度格式,为NCHW
        inputInfoItem.second->getInputData()->setLayout(Layout::NCHW);
        // 添加前处理resize操作,并且这个resize层是双线性插值的
        inputInfoItem.second->getPreProcess().setResizeAlgorithm(ResizeAlgorithm::RESIZE_BILINEAR);
        throw std::logic_error("Unsupported " +
                               std::to_string(inputInfoItem.second->getTensorDesc().getDims().size()) + "D "
                               "input layer '" + inputInfoItem.first + "'. "
                               "Only 4D input layers are supported");
// -----------------------------------------------------------------------
// ------------- 4. Loading model to the device --------------------------
std::string device = "CPU";
ExecutableNetwork executable_network = ie.LoadNetwork(network, device);

上述操作就是为前处理添加一个resize操作层,实际上这个PreProcess是支持很多操作的,例如归一化、减去均值等等,相当于就是在mo转ir的时候,插入的操作,大家可以查看相应的文档InferenceEngine::PreProcessInfo Class Reference看到它支持的各种操作。

好了,以上就是全部内容,在接下来的时间里,我应该会继续更新模型部署的内容,比如ssd的部署啊,trt的量化啊什么的,openvino的量化我也想试一试,奈何经历不够,又要吃饭,又想玩。

OpenVINO整活(一) 输入分辨率OpenVINO分为转换与部署两个部分,如下图所示在转换步中,需要将输入模型序列化后传入OpenVINO的MOModel Optimizer工具对模型进行优化,以得到IRIntermediate Representation中间表示,详细的内部行为可以参考Model Optimizer Developer Guide。接着,在部署步中,我们使用OpenVINO提供的Python或者CPP的api,进行编程以达到我们想要的结果:1) 载入ir文件, 2) 建立ie
ERROR:cannot reshape array of size 181944 into shape(1,22743,4) 出错的原理看这里:https://blog.csdn.net/Netceor/article/details/107330685 但是我实际是转模型的,只能看到这里的报错,print的相关信息已在tu中代码里注释了: 此时报错是第三步骤: #linux default OpenVINO path # 1. weights转换成pb模型 python convert_weights
openvino2022部署最新版yolov5v6.1模型demo openvino 2022.1.0 openvino-dev 2022.1.0 openvino-telemetry 2022.1.1 torch 1.8.1 torchvision 0.9.1
里面命令行参数较多,其中比较重要的参数为: -input_model: 为输入的训练的模型,如果使用的是caffe训练的模型则应该为XXX.caffemodel
--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 *:具有模型权重的模型
使用anaconda新建一个虚拟环境,假设叫openvino,使用这个虚拟环境 我的选择是这样的,安装命令在最下面,如果出现超时问题,可以再加一个--default-timeout=10000 安装结束后,可以用mo -h检验一下 二、模型下载和转换 以yolox-tiny为例 omz_downloader --name yolox-tiny -o /home/lwd/Downloads omz_converter --name yolox-tiny -d /hom
接着前面系列博客来讲,这里会来跑下OpenVINO的自带示例,会在多个硬件平台上来测试(包括Intel Movidius Neural Computer Stick 2),神经棒的配置介绍见博主上一篇博客。 Intel Movidius Neural Computer Stick 2使用(PC-Based Ubuntu)_竹叶青lvye的博客-CSDN博客接着博主前面的系列博客继续讲,这篇来介绍上Intel的第二代加速神经棒的使用,主要还是参考官网来配置。前面很多博客也都访问过多家公司的官网,比较下来,I
基于openvino和python环境实现yolox图像检测:踩坑记录 最近看到openvino在Github上开源了一部分openvino_contrib,计划支持ARM架构CPU,就想着学学Openvino, 毕竟买不起NCS,想着单刷树莓派,正好yolox宣称吊打yolo系列,有支持各种加速引擎,果断拿来试试,然后就苦逼 了,但最终填坑,所以想着记录一下,和大家分享一下。 先甩个openvino_contrib和yolox地址: Github:openvino_contrib Github:y
OpenVINO是一个深度学习推理框架,可用于将训练好的神经网络模型部署到各种硬件平台上进行推理。下面是在OpenVINO部署Yolo的一些步骤: 1. 下载和安装OpenVINO Toolkit。在OpenVINO官网下载并安装适合您操作系统的版本。 2. 下载Yolo的权重文件和配置文件。在Yolo官网上下载权重文件和配置文件。 3. 将Yolo模型转换为OpenVINO格式。使用OpenVINO提供的Model Optimizer工具将Yolo模型转换为OpenVINO格式。您需要使用以下命令: python mo_tf.py --input_model yolov3.weights --tensorflow_use_custom_operations_config extensions/front/tf/yolo_v3.json --input_shape [1,416,416,3] --data_type FP32 --output_dir yolov3_openvino --model_name yolov3 其中,yolov3.weights是您下载的权重文件,yolo_v3.json是一个自定义操作文件,用于告诉Model Optimizer如何处理Yolo模型。--input_shape参数指定输入张量的形状,--data_type参数指定数据类型,--output_dir参数指定输出文件夹,--model_name参数指定模型名称。 4. 运行OpenVINO推理引擎。使用OpenVINO Inference Engine API加载和推理转换后的模型。您需要编写一个Python脚本来完成这一步骤。以下是一个简单的示例: import cv2 import numpy as np from openvino.inference_engine import IECore # Load the OpenVINO model model_xml = 'yolov3_openvino/yolov3.xml' model_bin = 'yolov3_openvino/yolov3.bin' ie = IECore() net = ie.read_network(model=model_xml, weights=model_bin) # Load the input image img = cv2.imread('input.jpg') # Preprocess the input image input_blob = next(iter(net.inputs)) n, c, h, w = net.inputs[input_blob].shape img = cv2.resize(img, (w, h)) img = img.transpose((2, 0, 1)) img = img.reshape((n, c, h, w)) # Run inference exec_net = ie.load_network(network=net, device_name='CPU') output = exec_net.infer(inputs={input_blob: img}) # Process the output output_blob = next(iter(net.outputs)) output = output[output_blob][0] boxes = output[:, 0:4] confs = output[:, 4] class_ids = output[:, 5:].argmax(axis=-1) # Draw the predicted boxes on the input image for i in range(len(boxes)): if confs[i] > 0.5: x, y, w, h = boxes[i] cv2.rectangle(img, (int(x), int(y)), (int(x+w), int(y+h)), (0, 255, 0), 2) # Save the output image cv2.imwrite('output.jpg', img.transpose((1, 2, 0))) 这个脚本加载了转换后的Yolo模型,读取了输入图像,对图像进行预处理,运行了推理,处理了输出并将结果绘制在输入图像上,最后保存了输出图像。 这些步骤仅仅是一个简单的例子,如果您需要更复杂的操作,您需要仔细阅读OpenVINO文档,并参考OpenVINO的示例代码。
CSDN-Ada助手: 非常感谢博主五年来的辛勤创作,为我们带来了许多宝贵的知识和经验。你的这篇博客非常精彩,深入浅出,读后让人受益匪浅。希望博主继续保持创作热情,分享更多的知识和心得,让我们从中受益。再次感谢博主的奉献,祝愿你的创作道路越来越顺利! 为了方便博主创作,提高生产力,CSDN上线了AI写作助手功能,就在创作编辑器右侧哦~(https://mp.csdn.net/edit?utm_source=blog_comment_recall )诚邀您来加入测评,到此(https://activity.csdn.net/creatActivity?id=10450&utm_source=blog_comment_recall)发布测评文章即可获得「话题勋章」,同时还有机会拿定制奖牌。 在win的VS2015下编译SuperLU与BLAS的动态库 m0_38075933: 你编译的不是静态库?起个动态库的标题过分了吧? Azure Kinect 使用记录 (一) 麦克斯韦恶魔: 你好,当然可以啦,对于azure kinect,现有的python包就可以处理这个任务:k4a,还有很多功能类似的包。如果是kinect2及其之前的版本,我就不知道了,但原理都是一样的,即使用官方提供的sdk。 Azure Kinect 使用记录 (一) EXC0000: 楼主好,想问下可以离线读取mkv文件然后做骨架追踪吗 pycharm + ssh 跳板机 + 服务器 天源细雪: 秘钥挺好的,我这是动态口令……