PPYOLO垃圾检测+地平线旭日X3派部署(下)
介绍PPYOLO部署在地平线旭日X3派部署中,介绍如何利用地平线AI 工具链转换模型和 X3派部署问题。
请点击此处查看本环境基本用法.
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
此文章为搬运
原项目链接
更多推荐
所有评论(0)