使用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	#運行你的代碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章