请点击此处查看本环境基本用法.

Please click here for more detailed instructions.

1. 简介

在上一个教程中,我们介绍了如何利用百度PaddlePaddle中的PPYOLO模型训练垃圾检测模型,并导出了ppyolo.onnx模型。但仅利用onnx模型无法直接部署到地平线旭日X3派上,我们将拆分为模型转换和上版部署两个部分。

整体流程图:
在这里插入图片描述

1. 模型转换

1.1 地平线AI芯片工具链环境搭建

参考地平线AI工具链官方教程:
https://developer.horizon.ai/api/v1/fileData/documents_pi/ai_toolchain_develop/horizon_ai_toolchain_user_guide/chapter_2_prerequisites.html

1.2 模型转换

在上一篇教程中,我们获得了paddlepaddle 转换后得到的onnx模型,需要转化地平线交叉编译模型(.bin)。接下来利用地平线AI芯片工具链进行模型转换检测,确认是否所有运算均在BPU上运行。在

地平线AI芯片工具链docker中执行命令:

hb_mapper checker --model-type onnx --march bernoulli2 --model ppyolo.onnx

验证后打印log日志如下:
可以看到所有算子均支持在BPU下运行,下一步进行模型转换。

2022-10-08 15:48:34,726 file: hb_mapper.py func: hb_mapper line No: 73 Start hb_mapper....
2022-10-08 15:48:34,726 file: hb_mapper.py func: hb_mapper line No: 74 log will be stored in /mnt/trash_det/ppyolo/hb_mapper_checker.log
2022-10-08 15:48:34,727 file: hb_mapper.py func: hb_mapper line No: 75 hbdk version 3.31.1
2022-10-08 15:48:34,727 file: hb_mapper.py func: hb_mapper line No: 76 horizon_nn version 0.13.9
2022-10-08 15:48:34,727 file: hb_mapper.py func: hb_mapper line No: 77 hb_mapper version 1.8.7
2022-10-08 15:48:34,768 file: helper.py func: helper line No: 124 Model input names: ['image']
2022-10-08 15:48:34,770 file: hb_mapper_checker.py func: hb_mapper_checker line No: 104 Model type: onnx
2022-10-08 15:48:34,770 file: hb_mapper_checker.py func: hb_mapper_checker line No: 105 march: bernoulli2
2022-10-08 15:48:34,770 file: hb_mapper_checker.py func: hb_mapper_checker line No: 110 input names []
2022-10-08 15:48:34,770 file: hb_mapper_checker.py func: hb_mapper_checker line No: 111 input shapes {}
2022-10-08 15:48:34,770 file: hb_mapper_checker.py func: hb_mapper_checker line No: 117 Begin model checking....
2022-10-08 15:48:34,770 file: build.py func: build line No: 36 [Sat Oct  8 15:48:34 2022] Start to Horizon NN Model Convert.
2022-10-08 15:48:34,771 file: dict_parser.py func: dict_parser line No: 28 The input parameter is not specified, convert with default parameters.
2022-10-08 15:48:34,771 file: dict_parser.py func: dict_parser line No: 518 Parsing the hbdk parameter:{'hbdk_pass_through_params': '--O0'}
2022-10-08 15:48:34,771 file: build.py func: build line No: 144 HorizonNN version: 0.13.9
2022-10-08 15:48:34,771 file: build.py func: build line No: 148 HBDK version: 3.31.1
2022-10-08 15:48:34,771 file: build.py func: build line No: 36 [Sat Oct  8 15:48:34 2022] Start to parse the onnx model.
2022-10-08 15:48:34,810 file: onnx_parser.py func: onnx_parser line No: 191 Input ONNX model infomation:
ONNX IR version:          6
Opset version:            11
Producer:                 PaddlePaddle
Domain:                   none
Input name:               image, [1, 3, 416, 416]
Output name:              ..._1.tmp_0, [1, 13, 13, 18]
Output name:              ..._3.tmp_0, [1, 26, 26, 18]
2022-10-08 15:48:35,109 file: build.py func: build line No: 39 [Sat Oct  8 15:48:35 2022] End to parse the onnx model.
2022-10-08 15:48:35,111 file: build.py func: build line No: 280 Model input names: ['image']
2022-10-08 15:48:35,158 file: build.py func: build line No: 542 Saving the original float model: ./.hb_check/original_float_model.onnx.
2022-10-08 15:48:35,158 file: build.py func: build line No: 36 [Sat Oct  8 15:48:35 2022] Start to optimize the model.
2022-10-08 15:48:36,842 file: build.py func: build line No: 39 [Sat Oct  8 15:48:36 2022] End to optimize the model.
2022-10-08 15:48:36,881 file: build.py func: build line No: 558 Saving the optimized model: ./.hb_check/optimized_float_model.onnx.
2022-10-08 15:48:36,881 file: build.py func: build line No: 36 [Sat Oct  8 15:48:36 2022] Start to calibrate the model.
2022-10-08 15:48:36,885 file: calibration_data_set.py func: calibration_data_set line No: 67 There are 1 samples in the calibration data set.
2022-10-08 15:48:37,889 file: max_calibrater.py func: max_calibrater line No: 68 Run calibration model with max method.
2022-10-08 15:48:38,853 file: build.py func: build line No: 39 [Sat Oct  8 15:48:38 2022] End to calibrate the model.
2022-10-08 15:48:38,853 file: build.py func: build line No: 36 [Sat Oct  8 15:48:38 2022] Start to quantize the model.
2022-10-08 15:48:41,097 file: build.py func: build line No: 39 [Sat Oct  8 15:48:41 2022] End to quantize the model.
2022-10-08 15:48:41,590 file: build.py func: build line No: 572 Saving the quantized model: ./.hb_check/quantized_model.onnx.
2022-10-08 15:48:43,095 file: build.py func: build line No: 36 [Sat Oct  8 15:48:43 2022] Start to compile the model with march bernoulli2.
2022-10-08 15:48:43,767 file: hybrid_build.py func: hybrid_build line No: 123 Compile submodel: paddle-onnx_subgraph_0
2022-10-08 15:48:44,808 file: hbdk_cc.py func: hbdk_cc line No: 95 hbdk-cc parameters:['--O0', '--input-layout', 'NHWC', '--output-layout', 'NHWC']
2022-10-08 15:48:44,809 file: hbdk_cc.py func: hbdk_cc line No: 96 hbdk-cc command used:hbdk-cc -f hbir -m /tmp/tmph6o754nd/paddle-onnx_subgraph_0.bin -o /tmp/tmph6o754nd/paddle-onnx_subgraph_0.hbm --march bernoulli2 --progressbar --O0 --input-layout NHWC --output-layout NHWC
2022-10-08 15:48:45,451 file: build.py func: build line No: 39 [Sat Oct  8 15:48:45 2022] End to compile the model with march bernoulli2.
2022-10-08 15:48:45,452 file: node_info.py func: node_info line No: 54 The converted model node information:
========================================================
Node           ON   Subgraph  Type                       
---------------------------------------------------------
Conv_0         BPU  id(0)     HzSQuantizedConv           
Conv_1         BPU  id(0)     HzSQuantizedConv           
Conv_2         BPU  id(0)     HzSQuantizedConv           
MaxPool_0      BPU  id(0)     HzQuantizedMaxPool         
Conv_3         BPU  id(0)     HzSQuantizedConv           
Conv_4         BPU  id(0)     HzSQuantizedConv           
Conv_5         BPU  id(0)     HzSQuantizedConv           
Conv_6         BPU  id(0)     HzSQuantizedConv           
Conv_7         BPU  id(0)     HzSQuantizedConv           
Conv_8         BPU  id(0)     HzSQuantizedConv           
Conv_9         BPU  id(0)     HzSQuantizedConv           
AveragePool_0  BPU  id(0)     HzSQuantizedConv           
Conv_10        BPU  id(0)     HzSQuantizedConv           
Conv_11        BPU  id(0)     HzSQuantizedConv           
Conv_12        BPU  id(0)     HzSQuantizedConv           
Conv_13        BPU  id(0)     HzSQuantizedConv           
Conv_14        BPU  id(0)     HzSQuantizedConv           
AveragePool_1  BPU  id(0)     HzSQuantizedConv           
Conv_15        BPU  id(0)     HzSQuantizedConv           
Conv_16        BPU  id(0)     HzSQuantizedConv           
Conv_17        BPU  id(0)     HzSQuantizedConv           
Conv_18        BPU  id(0)     HzSQuantizedConv           
Conv_19        BPU  id(0)     HzSQuantizedConv           
AveragePool_2  BPU  id(0)     HzSQuantizedConv           
Conv_20        BPU  id(0)     HzSQuantizedConv           
Conv_21        BPU  id(0)     HzSQuantizedConv           
Conv_22        BPU  id(0)     HzSQuantizedConv           
Conv_23        BPU  id(0)     HzSQuantizedConv           
LeakyRelu_0    BPU  id(0)     HzLeakyRelu                
Conv_24        BPU  id(0)     HzSQuantizedConv           
LeakyRelu_1    BPU  id(0)     HzLeakyRelu                
Conv_25        BPU  id(0)     HzSQuantizedConv           
LeakyRelu_2    BPU  id(0)     HzLeakyRelu                
Resize_0       BPU  id(0)     HzQuantizedResizeUpsample  
Concat_0       BPU  id(0)     Concat                     
Conv_26        BPU  id(0)     HzSQuantizedConv           
LeakyRelu_3    BPU  id(0)     HzLeakyRelu                
Conv_27        BPU  id(0)     HzSQuantizedConv           
LeakyRelu_4    BPU  id(0)     HzLeakyRelu                
Conv_28        BPU  id(0)     HzSQuantizedConv           
Conv_29        BPU  id(0)     HzSQuantizedConv
2022-10-08 15:48:45,452 file: build.py func: build line No: 39 [Sat Oct  8 15:48:45 2022] End to Horizon NN Model Convert.
2022-10-08 15:48:45,456 file: onnx2horizonrt.py func: onnx2horizonrt line No: 3854 ONNX model output num : 2
2022-10-08 15:48:45,473 file: hb_mapper_checker.py func: hb_mapper_checker line No: 141 End model checking....

1.3 模型转换

首先设置工具链转换的配置文件config.yaml

# 模型转化相关的参数
model_parameters:
    # onnx浮点网络数据模型文件
    onnx_model: 'ppyolo.onnx'
    # 适用BPU架构
    march: "bernoulli2"
    # 指定模型转换过程中是否输出各层的中间结果,如果为True,则输出所有层的中间输出结果,
    layer_out_dump: False
    # 日志文件的输出控制参数,
    # debug输出模型转换的详细信息
    # info只输出关键信息
    # warn输出警告和错误级别以上的信息
    log_level: 'debug'
    # 模型转换输出的结果的存放目录
    working_dir: 'model_output'
    # 模型转换输出的用于上板执行的模型文件的名称前缀
    output_model_file_prefix: 'ppyolo_trashdet_416x416_nv12'


# 模型输入相关参数, 若输入多个节点, 则应使用';'进行分隔, 使用默认缺省设置则写None
input_parameters:
    # (可不填) 模型输入的节点名称, 此名称应与模型文件中的名称一致, 否则会报错, 不填则会使用模型文件中的节点名称
    input_name: "image"
    # 网络实际执行时,输入给网络的数据格式,包括 nv12/rgb/bgr/yuv444/gray/featuremap,
    # 如果输入的数据为yuv444, 模型训练用的是bgr(NCHW),则hb_mapper将自动插入YUV到BGR(NCHW)转化操作
    input_type_rt: 'nv12'
    # 转换后混合异构模型需要适配的输入数据排布,可设置为:NHWC/NCHW
    # 若input_type_rt配置为nv12,则此处参数不需要配置
    input_layout_rt: 'NHWC'
    # 网络训练时输入的数据格式,可选的值为rgb/bgr/gray/featuremap/yuv444
    input_type_train: 'rgb'
    # 网络训练时输入的数据排布, 可选值为 NHWC/NCHW
    input_layout_train: 'NCHW'
    # 模型网络的输入大小, 以'x'分隔, 不填则会使用模型文件中的网络输入大小,否则会覆盖模型文件中输入大小
    input_shape: '1x3x416x416'
    # 网络输入的预处理方法,主要有以下几种:
    # no_preprocess 不做任何操作
    # data_mean 减去通道均值mean_value
    # data_scale 对图像像素乘以data_scale系数
    # data_mean_and_scale 减去通道均值后再乘以scale系数
    norm_type: 'data_mean_and_scale'
    # 图像减去的均值, 如果是通道均值,value之间必须用空格分隔
    mean_value: 123.68 116.28 103.53
    # 图像预处理缩放比例,如果是通道缩放比例,value之间必须用空格分隔
    scale_value: 0.0171 0.0175 0.0174

calibration_parameters:
    # 模型量化的参考图像的存放目录,图片格式支持JPEG、BMP等格式,输入的图片
    # 应该是使用的典型场景,一般是从测试集中选择20~100张图片,另外输入
    # 的图片要覆盖典型场景,不要是偏僻场景,如过曝光、饱和、模糊、纯黑、纯白等图片
    # 若有多个输入节点, 则应使用';'进行分隔
    cal_data_dir: './images_f32'
    # 如果输入的图片文件尺寸和模型训练的尺寸不一致时,并且preprocess_on为true,
    # 则将采用默认预处理方法(skimage resize),
    # 将输入图片缩放或者裁减到指定尺寸,否则,需要用户提前把图片处理为训练时的尺寸
    preprocess_on: True
    # 模型量化的算法类型,支持kl、max、default、load,通常采用default即可满足要求, 若为QAT导出的模型, 则应选择load
    calibration_type: 'kl'

# 编译器相关参数
compiler_parameters:
    # 编译策略,支持bandwidth和latency两种优化模式;
    # bandwidth以优化ddr的访问带宽为目标;
    # latency以优化推理时间为目标
    compile_mode: 'latency'
    # 设置debug为True将打开编译器的debug模式,能够输出性能仿真的相关信息,如帧率、DDR带宽占用等
    debug: False
    # 编译模型指定核数,不指定默认编译单核模型, 若编译双核模型,将下边注释打开即可
    core_num: 2
    # 优化等级可选范围为O0~O3
    # O0不做任何优化, 编译速度最快,优化程度最低,
    # O1-O3随着优化等级提高,预期编译后的模型的执行速度会更快,但是所需编译时间也会变长。
    # 推荐用O2做最快验证
    optimize_level: 'O2'

在docker中执行模型转换命令:

hb_mapper makertbin --config config.yaml --model-type onnx

得到4个模型:

  • ppyolo_trashdet_416x416_nv12_original_float_model.onnx
  • ppyolo_trashdet_416x416_nv12_optimized_float_model.onnx
  • ppyolo_trashdet_416x416_nv12_quantized_model.onnx
  • ppyolo_416x416.bin

2.上板部署

代码仓库:https://c-gitlab.horizon.ai/HHP/box/hobot_perception/mono2d_trash_detection

2.1 TROS环境搭建

1)通过apt安装TROS快速体验(适用本教程)

https://developer.horizon.ai/api/v1/fileData/TogetherROS/quick_start/install_tros.html

2)如需进行二次开发,编译安装方法

https://developer.horizon.ai/api/v1/fileData/TogetherROS/quick_start/cross_compile.html

2.2 设置配置文件

ppyoloworkconfig.json配置文件说明

{ 
    "model_file":模型文件的路径 
    "model_name":模型名称 
    "dnn_Parser":设置选择内置的后处理算法,示例采用的解析方法同yolov3,采用"yolov3" 
    "model_output_count":模型输出branch个数 
    "class_num": 检测类别数 
    "cls_names_list": 检测类别具体标签 
    "strides": 每个输出branch步长 
    "anchors_table": 预设anchors比例 
    "score_threshold": 置信度阈值 
    "nms_threshold": NMS后处理IOU阈值 
    "nms_top_k": NMS后处理选取的框个数 
 }

2.3 实时运行

在地平线旭日X3派上运行:

# 复制配置文件
cp -r /opt/tros/lib/mono2d_trash_detection/config/ . 

# 设置mipi摄像头
export CAM_TYPE=mipi

# 运行dnn_node_example节点
ros2 launch dnn_node_example hobot_dnn_node_example.launch.py \ 
        config_file:=config/ppyoloworkconfig.json \
        msg_pub_topic_name:=ai_msg_mono2d_trash_detection \
        image_width:=1920 \
        image_height:=1080

实时运行效果如下,当前部署可以达到30FPS(实时):

在这里插入图片描述

实时演示视频:

在这里插入图片描述

终端日志打印:

在这里插入图片描述

2.4 本地回灌

在地平线旭日X3派终端上运行:

# 复制配置文件
cp -r /opt/tros/lib/mono2d_trash_detection/config/ . 

# 运行dnn_node_example节点
ros2 launch dnn_node_example hobot_dnn_node_example_feedback.launch.py \
        config_file:=config/ppyoloworkconfig.json \
        image:=config/trashDet0028.jpg 

回灌图片保存到本地效果如下:

在这里插入图片描述

终端日志打印:

在这里插入图片描述

3. 总结

至此,基于百度PaddlePaddle框架训练 + 地平线旭日X3派部署的教程到此介绍完毕,后续用户可借助地平线机器人开发平台,利用AI检测结果,开发更多有趣好玩的机器人项目。

参考连接:https://developer.horizon.ai/api/v1/fileData/TogetherROS/index.html

此文章为搬运
原项目链接

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐