专栏算法工具链resizer模型使用与部署

resizer模型使用与部署

颜值即正义2022-09-29
349
7

1 前言

本文主要介绍在地平线开发板上针对resizer模型的使用与部署,如果您是一个初学者,对于该内容可能会有以下几点疑问:

1.什么是resizer?什么是resizer模型?
2.为什么要用resizer模型?
3.如何得到resizer模型?
4.resizer模型如何部署?
下面我将以具体的示例来对以上几个问题进行解释。
答1:resizer是指芯片上用于处理图像缩放的一个功能模块,可以把图像(nv12) 里的一个指定 ROI,缩放成指定的大小,缩放的方法是双线性插值,通过BPU的functioncall驱动。在一些人工智能业务场景中需要使用到该模块的算法模型,称之为resizer模型。
答2:为了方便大家理解,以车辆检测与识别场景为例,如下图所示。先通过一个上游网络检测得到图片中不同车辆的位置信息,把检测到的车辆图片信息送入小网络进行识别前,需要先进行尺寸缩放,为了适配类似业务场景,加快图片尺寸缩放速度,地平线芯片上提供针对resizer模型的专门加速硬件模块。
答3:在模型转换时,将编译参数 input_source 设置为 {'input_name': 'resizer'}即可生成resizer模型,注意:该参数配置为resizer时,inpurt_type_rt参数仅支持配置为nv12和gray,具体参数配置细节可参考 地平线算法工具链用户手册4.1.1.6. 模型量化与编译 中的介绍。
答4:在编译得到resizer模型后,具体使用和部署细节将在第3节详细介绍。
注: 文中用户手册目录和open_explorer开发包的目录结构,均以XJ3为例进行讲解,J5用户请在类似目录下进行实践。

2 resizer模型约束

resizer模型推理时,输入从DDR读取,会先使用roi从原始图像中抠图后resize到模型输入大小,输出存储在一块特殊的片上内存中,只有BPU可以读取,且读取的过程会改变数据的排布,所以resizer的输出只能送入BPU用作模型推理,上述过程中,一些约束信息如下表所示,

XJ3芯片平台:
J5芯片平台:
avatar
H和W方向的缩放倍数均有限制,以下src_len表示roi.size.h或roi.size.w。dst_len表示输出的h或w。
step = ((src_len - 1) * 65536 + (dst_len - 1) / 2) / (dst_len - 1)
step需要在范围[0, 262143]内,即缩放倍数在[1/4, 65536)之内。如果相关接口中有keep ratio选项,并且设置该参数为true。则限制需要以keep ratio之后的输出尺寸来考虑step限制。
h_ratio = roi.size.h * 65536 / dest_h
w_ratio = roi.size.w * 65536 / dest_w
如果h_ratio>w_ratio,则需要在上述公式中dest_w调整为
roi.size.w * dest_h / roi.size.h
如果w_ratio>h_ratio,则需要在上述公式中dest_h调整为
roi.size.h * dest_w / roi.size.w

resizer模型目前支持多输入的nv12数据,resizer常用的输出尺寸(HxW)如下:

  • 128x128

  • 128x64

  • 64x128

  • 160x96

3 resizer模型使用流程

以horizon_xj3_open_explorer_v2.6.2b-py38_20230606开发包(简称OE包)里的roi_infer示例,路径为ddk/samples/ai_toolchain/horizon_runtime_sample/code/01_api_tutorial/roi_infer做一个简要说明,使用的resizer模型是mobilenetv1_128x128_resizer_nv12.bin,路径为/open_explorer/ddk/samples/ai_toolchain/model_zoo/runtime/mobilenetv1。

3.1 所需文件结构说明

resizer模型示例是在horizon_runtime_sample目录下,该目录下需要用到的目录结构如下所示:

├── code # 开发机中编译示例源码
│ ├── 01_api_tutorial # dnn API使用示例代码
│ │ └──roi_infer # resizer模型推理示例
│ ├── build_xj3.sh # xj3 ARM端编译脚本
│ ├── CMakeLists.txt
│ ├── deps
│ │ └──aarch64 # xj3 ARM端编译依赖库
├── xj3 # 板端运行目录结构
│ ├── data # 预置图片数据文件
│ ├── model # resizer模型文件
│ │ └──model_name.bin # mobilenetv1_128x128_resizer_nv12.bin
│ ├── script # ARM端示例运行脚本
│ ├── 01_api_tutorial # dnn API使用示例代码
│ └──roi_infer.sh # resizer板端运行脚本
└── README.md
大家初次使用时,重点关注code/build_xj3.sh和xj3/01_api_tutorial/roi_infer.sh两个脚本即可。

3.2 环境准备

想要完成整个resizer模型的使用和部署,需要用到开发机和开发板,因此环境准备工作包含 开发机部署 和 开发板部署 两个部分,在OE包中,地平线分别为大家提供了开发机中docker环境部署脚本run_docker.sh和开发板端环境部署脚本install.sh,具体使用方式欢迎参考地平线AI工具链用户手册2.1 环境部署

3.3 板端部署的主要流程

resizer模型板端部署的主要流程如下图所示,首先通过预测库中提供的API,加载resizer混合异构模型(model_name.bin),获取模型输入输出信息,准备输入输出数据的内存,在获取到nv12输入数据后,使用hbDNNRoiInfer接口进行模型推理,然后将推理得到的结果进行后处理,当然,这些操作完成后,还要对相关资源进行释放。
整个过程中,与常规模型部署不同的是使用了hbDNNRoiInfer这个API进行模型推理,下面对该API的参数和返回值进行详细解读。

参数介绍:

[out] taskHandle:任务句柄指针。
[in/out] output:推理任务的输出。
[in] input:推理任务的输入。
[in] rois:Roi框信息。
[in] roiCount:Roi框数量。
[in] dnnHandle:dnn句柄指针。
[in] inferCtrlParam:控制推理任务的参数。

返回值:

返回 0 则表示API成功执行,否则执行失败。

关于该API更多注解欢迎参考 算法工具链用户手册5.2.3.4.2 hbDNNRoiInfer()

其中需要注意的有四个参数,分别是output, input, rois, roiCount,为了方便大家理解,下面举两个例子进行介绍。

例1:下游网络是 单输入单输出单batch模型 (model_batch=1,即模型实际推理时,输入给模型的 batch_size=1),且输入源为resizer时(在转换yaml中配置input_source参数为resizer),也就是OE包中所提供示例的情况,如下图所示,传感器采集到1张图片,经过上游网络后,获取到两个roi区域(roi0, roi1),也就是模型需要推理的数据批数data_batch=2。通过resizer模块处理后,送入下游网络,下游网络是一个单输入网络,输入为:input0(128x64),下游网络有一个输出,命名为:output0。

此时,推理任务的输入input可以依次表示为:

推理任务的输出Output可以表示为:

其中Output0中内容包括:roi0_output0, roi1_output0,可以理解为data_batch=2,model_batch=1的模型推理。

注意:hbDNNRoiInfer函数中的的输入input数据始终是上游网络的输入原图。
例2:下游网络是多输入多输出单batch模型(model_batch=1),且每个输入源均是resizer时,如下图所示,传感器采集到1张图片,经过上游网络后,获取到两个roi区域(roi0, roi1),通过resizer模块处理后,送入下游网络,下游网络是一个三输入网络,三个输入分别为:input0(128x128)、input1(128x64)、input2(64x128),下游网络有两个输出,分别命名为:output0、output1。

此时,推理任务的输入input可以依次表示为:

其中,[roi0_input0, roi1_input1, roi2_input2]作为data_batch0的数据完成一次推理,[roi3_input0, roi4_input1, roi5_input2]作为data_batch1的数据完成一次推理。
推理任务的输出Output可以依次表示为:

其中Output0中内容包括:data_batch0_output0, data_batch1_output0,Output1中内容包括:data_batch0_output1, data_batch1_output1,因此,在准备输出内存时需要结合data_batch数量和对应输出分支的shape来进行分配。

例3:地平线工具链从OE1.1.68版本开始支持model_batch_resizer的场景,针对多data_batch的场景有一定的加速效果,举一个例子来介绍一下。假设模型有 3 个输入分支(2个resizer输入源,1个ddr输入源)和 1 个输出分支,并以 model_batch=2 编译,模型共需处理 3 批数据共 6 个 roi(即data_batch=3,每批数据有2个roi)。

此时模型推理这 3 批数据需要准备独立地址的 input_tensor 数量为 3个输入分支 x 3批数据 = 9。

另假设模型输入/输出的静态信息如下:

  • 模型输入(model_info):

    • tensor_0_resizer: [2, 3, 128, 128]

    • tensor_1_resizer: [2, 3, 256, 256]

    • tensor_2_ddr: [2, 80, 1, 100]

  • 模型输出(model_info):

    • tensor_out:[2, 100, 1, 56]

那么模型在推理时的动态信息则为:

  • 模型输入(input_tensors):

    • [1x3x128x128, 1x3x256x256, 1x80x1x100, 1x3x128x128, 1x3x256x256, 1x80x1x100, 1x3x128x128, 1x3x256x256, 1x80x1x100]

  • 模型输出(output_tensors):

    • [4x100x1x56]

其中,因为 model_batch = 2,所以底层 BPU 单次执行可处理 2 批数据;又因为 data_batch = 3,所以 output_tensor 最高维的计算公式为 ceil[(data_batch) / model_batch] * model_batch,可见其一定为 model_batch 的整数倍,这也是 BPU 硬件指令要求,缺少的输入会自动忽略计算。注意:这里模型输出[0~2x100x1x56]是有效数据,最后一组是无效数据。

3.4 hbDNNRoiInfer调用源码简析

在文件code/01_api_tutorial/roi_infer/src/roi_infer.cc中有使用hbDNNRoiInfer推理模型的全流程的详细代码,这里对该API调用部分代码进行简单呈现。

3.5 工程编译

工程编译的参考过程如下:
1. 执行horizon_runtime_sample/code目录下的build_xj3.sh脚本即可一键编译生成xj3开发板端的可执行程序和对应依赖库,分别存放在xj3/script/aarch64目录下的bin和lib子目录;
2. 正确完成编译后,xj3/script/aarch64的目录结构为:
aarch64
├── bin
│ └── roi_infer # 编译产生的可执行文件
└── lib # 编译执行依赖相关库
├── libdnn.so
├── libhbrt_bernoulli_aarch64.so
└── libopencv_world.so.3.4
3. 将xj3文件夹与roi_infer相关的文件传输到x3开发板上,传输文件列表如下:
├── xj3 # 板端运行目录结构
│ ├── data # 预置图片数据文件
│ ├── model # resizer模型文件
│ │ └──model_name.bin # 真实路径为model/runtime/mobilenetv1/xxx.bin
│ ├── script # ARM端示例运行脚本
│ ├── aarch64 # 板端可执行程序和对应依赖库,执行build_xj3.sh后自动生成
│ ├── 01_api_tutorial # dnn API使用示例代码
│ └──roi_infer.sh # resizer板端运行脚本

推荐您使用scp命令进行文件传输,执行命令可参考:

其中,board_ip为xj3开发板的IP地址,请确保在开发机上可以访问该IP。

3.6 上板推理

正确完成编译后,进入开发板端/userdata/xj3/script/01_api_tutorial/目录下,执行roi_infer.sh脚本。

运行结果如下:

至此,完成resizer模型推理和结果输出的全过程。

4 板端使用工具评测resizer模型

4.1 hrt_model_exec工具简介

hrt_model_exec 是一个模型执行工具,提供了模型推理 infer、模型性能分析 perf 和查看模型信息 model_info 三类功能。 关于该工具的具体信息可参考地平线工具链手册 5.5.2. hrt_model_exec工具介绍
hrt_model_exec工具从1.13.1版本开始,新增roi_infer和roi两个参数用于支持resizer模型推理和性能评测,roi_infer输入为bool类型,用于使能resizer模型推理,roi输入为string类型,用于指定推理resizer模型时所需的roi区域。在板端,可通过hrt_model_exec -v指令查看工具版本,通过hrt_model_exec -h查看工具使用详情,下面将详细介绍如何使用该工具推理评测包含resizer输入源的模型。
当模型包含resizer输入源时,infer 和perf 功能都需要设置 roi_infer 为true,并且配置与输入源一一对应的 input_file 和 roi 参数。例如:某模型有三个输入,输入源顺序分别为[ddr, resizer, resizer],则评测两组输入数据的命令如下:
注意:input_file的输入使用英文的逗号隔开,且不能有空格;每个 roi 输入之间用英文的分号隔开。
针对model_batch大于1的resizer模型场景,使用上需要注意model_file和input_file参数的配置。例如:某模型有一个输入,输入源为resizer,model_batch为2,则推理data_batch=1数据的命令如下:

此时,输出的第一维是有效数据,第二维是无效数据

推理data_batch=2数据的命令如下:

4.2 板端实测

以第3节中的mobilenetv1_128x128_resizer_nv12.bin模型为例,使用hrt_model_exec工具的模型推理 infer、模型性能分析 perf两类功能,展示hrt_model_exec工具评测resizer模型的过程,需要的文件有:
  • infer模型推理
    运行命令:

输出结果:

  • perf评测性能latency
    运行命令:

输出结果:

  • perf评测性能FPS
    运行命令:

输出结果:

算法工具链
征程3征程5杂谈
+9
评论3
0/1000
  • higher
    Lv.1

    RoiInfer是,输入原始图像的尺寸如何指定?比输入1920x1080,需要crop resize到128x128

    2023-02-27
    0
    3
    • 颜值即正义回复higher:

      输入原始图像的尺寸满足限制即可,具体缩放形式需要自己是尝试哈

      2023-02-27
      0
    • higher回复颜值即正义:

      输入图像尺寸在哪里可以配置,如何配置? 还是在运行代码中动态指定?

      2023-02-27
      0
    • 好娃金刚回复higher:

      输入图像尺寸在哪里可以配置,如何配置? 还是在运行代码中动态指定?

      2023-05-25
      0
  • 好娃金刚
    Lv.1

    输入图像尺寸在哪里可以配置,如何配置? 还是在运行代码中动态指定?

    2023-05-25
    0
    1
    • 颜值即正义回复好娃金刚:

      你好,您说的这个输入图像尺寸是指下游resizer模型的输入尺寸对嘛?这取决于您的下游模型自身的尺寸,体现在yaml文件中是input_shape这个参数

      2023-05-25
      0
  • hunterkan
    Lv.1

    ?

    2022-09-30
    0
    0