使用Openvino部署MXNET(Gluon)模型

所用的目标检测网络为GluonCV中的ssd_512_resnet50_v1_voc,在此使用预训练模型

openvino安装教程自己百度,我使用的是2019_R3.1版本,mxnet为1.5.1版本,运行设备为Intel Movidius Myriad X VPU


有时候在做边缘计算或者没有强大的GPU支持时候,mxnet以及pytorch,tf等框架的前向传播的实时性是达不到要求的,所以可以考虑考虑Intel的openvino。我在使用自己训练的火情识别的边缘计算设备时候就需要openvino进行加速。也使用过tensorrt,但是mxnet转onnx时候失败了,有的算子mxnet没有实现,自己也没精力去研究,干脆用openvino试试,发现还真挺好使。该文章进行记录,说不定能帮助大家。

总体步骤:

1.加载SSD的gluon(0.5.0版本,比这个高的版本的ssd结构不一样,openvino_2019.3.334是不能直接转的,需要自己写不支持的层)模型,生成*.params与*.json文件
2.使用openvino提供的工具mo_mxnet.py进行转换
3.使用openvino进行前向传播(部署)



STEP1 加载SSD的gluon模型,生成*.params与*.json文件

代码很简单,如下(数据输入我使用比较常见的(1,3,512,512),可以自行设置,同时下文需要)

from mxnet import nd
from gluoncv import model_zoo

weight_path = "./hardhat.params"

net = model_zoo.get_model("ssd_512_resnet50_v1_voc", pretrained=True)
net.hybridize()

data_shape = (1, 3, 512, 512)

input_data = nd.random.uniform(-1, 1, data_shape)
_ = net(input_data)

net.export("TestSSD")

运行成功后,会在本地生成以下文件
bin和xml文件最重要
第一步完成

STEP2 使用openvino提供的工具mo_mxnet.py进行转换

mo_mxnet.py是openvino提供的工具,位置在<INSTALL_DIR>/deployment_tools/model_optimizer

我使用的mac默认安装位置是/opt/intel/openvino

然后cd到第一步刚刚生成文件的路径下
使用命令:

python /opt/intel/openvino/deployment_tools/model_optimizer/mo_mxnet.py --input_model TestSSD-0000.params \
    --input_shape [1,3,512,512]-enable_ssd_gluoncv --data_type FP16

命令解释:
--input_model 这个不解释了,就是会读取刚刚生成的*.params与*.json文件

--input_shape 因为我们生成的.json文件内是没有指定网络输入的,所以这里我们要指定网络输入数据shape,我使用比较常见的 (1, 3, 512, 512) 此外我用zsh会报错,后来转bash成功运行

--enable_ssd_gluoncv 因为我们使用的gluoncv中的ssd包含了一些layer '_contrib_box_nms',openvino不支持,所以openvino使用DetectionOutput layer代替,通过enable_ssd_gluoncv开启该替换

--data_type 后面的运行代码需要FP16精度,你的准备转换的模型可以不需要FP16,mo_mxnet.py会自动帮你转

第二步完成

STEP3 使用openvino进行前向传播(部署)

前向传播所经过的步骤:

  1. Read the Intermediate Representation
  2. Prepare inputs and outputs format
  3. Create Inference Engine Core object
  4. Compile and Load Network to device
  5. Set input data
  6. Execute
  7. Get the output
    大概是这么多的步骤,我根据以上步骤粗糙的写了一个脚本,以供大家参考
'''
@Author: your name
@Date: 2020-01-18 13:15:51
@LastEditTime : 2020-01-18 13:33:02
@LastEditors  : Please set LastEditors
@Description: In User Settings Edit
@FilePath: /Desktop/ie.py
'''
"""01. Predict with pre-trained SSD models
==========================================

This article shows how to play with pre-trained SSD models with only a few
lines of code.

First let's import some necessary libraries:
"""

from gluoncv import model_zoo, data, utils
from matplotlib import pyplot as plt
from openvino.inference_engine import ie_api as ie
import numpy as np

######################################################################
# Load a pretrained model
# -------------------------
#
# Let's get an SSD model trained with 512x512 images on Pascal VOC
# dataset with ResNet-50 V1 as the base model. By specifying
# ``pretrained=True``, it will automatically download the model from the model
# zoo if necessary. For more pretrained models, please refer to
# :doc:`../../model_zoo/index`.
gluoncv_net = model_zoo.get_model('ssd_512_resnet50_v1_voc', pretrained=True)
core = ie.IECore()
net = ie.IENetwork('ssd-fp32-0000.xml', 'ssd-fp32-0000.bin')

######################################################################
# Pre-process an image
# --------------------
#
# Next we download an image, and pre-process with preset data transforms. Here we
# specify that we resize the short edge of the image to 512 px. But you can
# feed an arbitrarily sized image.
#
# You can provide a list of image file names, such as ``[im_fname1, im_fname2,
# ...]`` to :py:func:`gluoncv.data.transforms.presets.ssd.load_test` if you
# want to load multiple image together.
#
# This function returns two results. The first is a NDArray with shape
# `(batch_size, RGB_channels, height, width)`. It can be fed into the
# model directly. The second one contains the images in numpy format to
# easy to be plotted. Since we only loaded a single image, the first dimension
# of `x` is 1.

im_fname = utils.download('https://github.com/dmlc/web-data/blob/master/' +
                          'gluoncv/detection/street_small.jpg?raw=true',
                          path='street_small.jpg')
x, img = data.transforms.presets.ssd.load_test(im_fname, short=512)
print('Shape of pre-processed image:', x.shape)

######################################################################
# Inference and display
# ---------------------
#
# The forward function will return all detected bounding boxes, and the
# corresponding predicted class IDs and confidence scores. Their shapes are
# `(batch_size, num_bboxes, 1)`, `(batch_size, num_bboxes, 1)`, and
# `(batch_size, num_bboxes, 4)`, respectively.
#
# We can use :py:func:`gluoncv.utils.viz.plot_bbox` to visualize the
# results. We slice the results for the first image and feed them into `plot_bbox`:

exec_net = core.load_network(net, device_name="MYRIAD", num_requests=1)
input_names = net.inputs.keys()
input_data = list(x.asnumpy())
assert(len(input_data) == len(input_names))
input = dict(zip(input_names, input_data))
exec_net.requests[0].infer(input)
res = exec_net.requests[0].outputs
box1 = res['1208/DetectionOutput_']		# 这个1208的参数可能需要修改,自行输出res查看就知道怎么改了
"""
bbox:   box1[0,0,:,3:7]
scores: box1[0,0,:,2]
label:  box1[0,0,:,1]
"""
ax = utils.viz.plot_bbox(img, box1[0,0,:,3:7], box1[0,0,:,2],
                         box1[0,0,:,1], class_names=gluoncv_net.classes)
plt.show()

注:

  1. 我运行的设备是插着intel的计算棒的电脑,所以我使用 DEVICE = "MYRIAD", 你可以用CPU,但貌似要装其他OPENCL啥子的东西
  2. 分了一个线程去读取图片,没写退出程序的逻辑,所以一旦没再看到 预处理图片输出,就可以Ctrl+C退出了
  3. info的内容如下(数字代表位置): 0->当前结果所对应的图片索引(多张图片整合在一个Batch时会需要它,本文中就一张图片) 1->label的索引 2->置信度 3~6->原图中的左上右下座标点(xmin, ymin, xmax, ymax)
  4. 要是你的平台不是普通的x86,mxnet和gluoncv这俩库可能安装不了,是需要自行从源码编译安装mxnet和gluoncv的 或者自己根据gluoncv的预处理函数data.transforms.presets.ssd.load_test以及画框的函数utils.viz.plot_bbox自己写一个
  5. 这个可能要管理员权限运行(我遇到了NC_ERROR),sudo su -> python3 test.py 或者写一个sh脚本,然后在普通用户下用sudo运行它,比如下面这个
#!/bin/bash
source /home/rainweic/intel/openvino/bin/setupvars.sh		# 改你openvino安装的路径
python3 test.py	#运行你的代码
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章