5.3. BPU 算法推理

5.3.1. 概述

本文档主要介绍了地平线Python版本推理引擎API、数据结构、使用方法。 通过阅读本文档用户可以在开发板上,利用API通过简单的函数调用,来完成模型加载、数据及Tensor的准备、模型推理、获取模型输出等操作。

5.3.2. 数据相关类及结构

class hobot_dnn.pyeasy_dnn.TensorProperties
Parameters:
    1、tensor_type (string):表示tensor的数据类型,例如:NV12、BGR、float32等
    2、dtype (string):表示数据的存储类型,同numpy数据类型,例如:int8、uint8、float32等
    3、layout (string):表示数据排布格式,NHWC或者NCHW
    4、shape (tuple):表示存储数据的shape信息,例如:(1,3,224,224)
class hobot_dnn.pyeasy_dnn.pyDNNTensor
Parameters:
    1、properties (TensorProperties):表示模型tensor的属性,详细参见 `class hobot_dnn.pyeasy_dnn.TensorProperties` 
    2、buffer (numpy):表示模型tensor中的数据,数据访问方式同numpy
    3、name (string):表示模型tensor的名称
class hobot_dnn.pyeasy_dnn.Model
Parameters:
    1、name (string):表示模型名称
    2、inputs (tuple(pyDNNTensor)):表示模型的输入tensor信息
    3、outputs (tuple(pyDNNTensor)):表示模型的输出tensor信息
    4、forward (args &args, kwargs &kwargs):模型推理函数接口,输入模型推理所必要的参数,返回模型推理结果
        parameters:
            args: 提供三种形式的tensor输入,详细使用参考文末示例,或者SDK的示例脚本
                非resizer模型:
                    a. numpy:单输入模型场景,直接提供numpy数据进行推理
                    b. list[numpy, numpy, ...]:多输入模型场景,将numpy数据打包成list,list长度应当为模型的输入个数
                resizer模型:
                    a. list[list[numpy, list], list[numpy, list], ...]:将numpy数据与roi框的信息打包成一个list,作为一个tensor输入,多个tensor打包成一个list,作为模型整体输入
            kwargs:core_id (int):表示模型推理的core id,可为0,1,2,默认为0表示任意核推理。
            kwargs:priority (int):表示当前模型推理任务的优先级,范围[0~255],越大优先级越高。
        returns: 接口返回模型输出结果
            非resizer模型:
                a. 输出为一维tuple: tuple(pyDNNTensor),tuple长度为模型输出个数; 
            resizer模型:
                a. 输出为二维tuple: tuple(tupe(pyDNNTensor)),len(output)长度为roi的数量,len(output[0])长度为模型单个roi输出数量。

NV12数据说明 根据 NV12 数据类型本身的特点,在准备 numpy 数据时,应当保证 shape=(h * 3 / 2, w) ,确保数据的合法的性。 对于 NV12 输入类型的模型,获取得到的输入 shape 信息为 shape=(n,c,h,w)shape=(n,h,w,c),其 shape 保留了原始图像的 hw 信息,c 通道数值无意义,不作为参考。

5.3.3. API接口

python推理接口提供load函数,用于加载模型,并且返回一个tuple

hobot_dnn.pyeasy_dnn.load(model_file)
接口支持两种模型加载方式:
    1、输入模型的文件路径,加载单个模型,或者单个pack模型
        model_file = "/userdata/single_model.bin"
        models = hobot_dnn.pyeasy_dnn.load(model_file)
    2、输入模型的文件列表,加载多个模型
        model_file = ["model1.bin", "model2.bin"]
        models = hobot_dnn.pyeasy_dnn.load(model_file)
接口返回hobot_dnn.pyeasy_dnn.Model类型的tuple列表

5.3.4. 示例

from hobot_dnn import pyeasy_dnn as dnn
import numpy import np

# 加载一个单输入NV12模型
models = dnn.load('./fcos_512x512_nv12.bin')
# 获取模型输入信息
input_dtype = models[0].inputs[0].properties.dtype
# 构造模型NV12输入数据
tensor = np.zeros((768, 512), dtype=input_dtype)
outputs = models[0].forward(tensor)
# 获取模型输出数据,类型为numpy数据
output_buffer = outputs[0].buffer

# 加载一个多输入bgr模型
models = dnn.load('./mobilenet_416x4126_bgr.bin')
shape1 = models[0].inputs[0].properties.shape
dtype1 = models[0].inputs[0].properties.dtype
shape2 = models[0].inputs[1].properties.shape
dtype2 = models[0].inputs[1].properties.dtype
# 构造模型数据
tensor1 = np.ones(shape1, dtype=type1)
tensor2 = np.zeros(shape2, dtype=dtype2)
input_data=[tensor1, tensor2]
outputs = models[0].forward(input_data)
# 获取模型输出数据,类型为numpy数据
output_buffer = outputs[0].buffer

# 加载resizer模型
models = dnn.load('resizer_512x512_nv12.bin')
# 构造模型NV12数据
data1 = np.zeros((768, 512), dtype='uint8')
roi1 = [18, 20, 99, 99]
tensor1 = [data1, roi1]

data2 = np.zeros((624, 416), dtype='uint8')
roi2 = [20, 22, 97, 97]
tensor2 = [data2, roi2]

input_data = [tensor1, tensor2]
outputs = models[0].forward(input_data)
# 模型输入roi框数量为2
assert len(outputs) == 2
# 模型单个roi框对应的输出tensor为1个
assert len(outputs[0]) == 1
# 获取模型输出数据,类型为numpy数据
output_buffer1 = outputs[0][0].buffer
output_buffer2 = outputs[1][0].buffer