8. 通用pp-yoloe模型部署

8.1. 引言

本文档介绍了如何将ppyoloe架构的模型部署在cv181x开发板的操作流程,主要的操作步骤包括:

  • ppyoloe模型pytorch版本转换为onnx模型

  • onnx模型转换为cvimodel格式

  • 最后编写调用接口获取推理结果

8.2. pt模型转换为onnx

PP-YOLOE是基于PP-Yolov2的Anchor-free模型,官方仓库在[PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection)

获取官方仓库代码并安装:

git clone https://github.com/PaddlePaddle/PaddleDetection.git

# CUDA10.2
python -m pip install paddlepaddle-gpu==2.3.2 -i https://mirror.baidu.com/pypi/simple

其他版本参照官方安装文档[开始使用_飞桨-源于产业实践的开源深度学习平台 (paddlepaddle.org.cn)](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/install/pip/linux-pip.html)

onnx导出可以参考官方文档[PaddleDetection/deploy/EXPORT_ONNX_MODEL.md at release/2.4 · PaddlePaddle/PaddleDetection (github.com)](https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.4/deploy/EXPORT_ONNX_MODEL.md)

本文档提供官方版本直接导出方式以及算能版本导出onnx,算能版本导出的方式需要去掉检测头的解码部分,方便后续量化,解码部分交给TDL_SDK实现

【官方版本导出】

可以使用PaddleDetection/tools/export_model.py导出官方版本的onnx模型

使用以下命令可以实现自动导出onnx模型,导出的onnx模型路径在output_inference_official/ppyoloe_crn_s_300e_coco/ppyoloe_crn_s_300e_coco_official.onnx

cd PaddleDetection
python \
tools/export_model_official.py \
-c configs/ppyoloe/ppyoloe_crn_s_300e_coco.yml \
-o weights=https://paddledet.bj.bcebos.com/models/ppyoloe_crn_s_300e_coco.pdparams

paddle2onnx \
--model_dir \
output_inference/ppyoloe_crn_s_300e_coco \
--model_filename model.pdmodel \
--params_filename model.pdiparams \
--opset_version 11 \
--save_file output_inference_official/ppyoloe_crn_s_300e_coco/ppyoloe_crn_s_300e_coco_official.onnx

参数说明:

  • -c 模型配置文件

  • -o paddle模型权重

  • –model_dir 模型导出目录

  • –model_filename paddle模型的名称

  • –params_filename paddle模型配置

  • –opset_version opset版本配置

  • –save_file 导出onnx模型的相对路径

【算能版本导出】

为了更好地进行模型量化,需要将检测头解码的部分去掉,再导出onnx模型,使用以下方式导出不解码的onnx模型

将yolo_export/pp_yolo_export.py复制到tools/目录下,然后使用如下命令导出不解码的pp-yoloe的onnx模型

python \
tools/export_model_no_decode.py \
-c configs/ppyoloe/ppyoloe_crn_s_300e_coco.yml \
-o weights=https://paddledet.bj.bcebos.com/models/ppyoloe_crn_s_300e_coco.pdparams

paddle2onnx \
--model_dir \
output_inference/ppyoloe_crn_s_300e_coco \
--model_filename model.pdmodel \
--params_filename model.pdiparams \
--opset_version 11 \
--save_file output_inference/ppyoloe_crn_s_300e_coco/ppyoloe_crn_s_300e_coco.onnx

参数参考官方版本导出的参数设置

小技巧

如果需要修改模型的输入尺寸,可以在上述导出的onnx模型进行修改,例如改为384x640的输入尺寸,使用以下命令进行修改:

python -m paddle2onnx.optimize \
--input_model ./output_inference/ppyoloe_crn_s_300e_coco/ppyoloe_crn_s_300e_coco.onnx \
--output_model ./output_inference/ppyoloe_crn_s_300e_coco/ppyoloe_384.onnx \
--input_shape_dict "{'x':[1,3,384,640]}"

yolo_export中的脚本可以通过SFTP获取:下载站台:sftp://218.17.249.213 帐号:cvitek_mlir_2023 密码:7&2Wd%cu5k

通过SFTP找到下图对应的文件夹:

/home/公版深度学习SDK/yolo_export.zip

8.3. onnx模型转换cvimodel

cvimodel转换操作可以参考cvimodel转换操作可以参考yolo-v5移植章节的onnx模型转换cvimodel部分。

8.4. TDL_SDK接口说明

### 预处理参数设置

预处理的设置接口如下所示

// set preprocess and algorithm param for ppyoloe detection
// if use official model, no need to change param
CVI_S32 init_param(const cvitdl_handle_t tdl_handle) {
  // setup preprocess
  YoloPreParam preprocess_cfg =
      CVI_TDL_Get_YOLO_Preparam(tdl_handle, CVI_TDL_SUPPORTED_MODEL_PPYOLOE);

  for (int i = 0; i < 3; i++) {
    printf("asign val %d \n", i);
    preprocess_cfg.factor[i] = 0.003922;
    preprocess_cfg.mean[i] = 0.0;
  }
  preprocess_cfg.format = PIXEL_FORMAT_RGB_888_PLANAR;

  printf("setup ppyoloe param \n");
  CVI_S32 ret =
      CVI_TDL_Set_YOLO_Preparam(tdl_handle, CVI_TDL_SUPPORTED_MODEL_PPYOLOE, preprocess_cfg);
  if (ret != CVI_SUCCESS) {
    printf("Can not set ppyoloe preprocess parameters %#x\n", ret);
    return ret;
  }

  // setup yolo algorithm preprocess
  YoloAlgParam ppyoloe_param =
      CVI_TDL_Get_YOLO_Algparam(tdl_handle, CVI_TDL_SUPPORTED_MODEL_PPYOLOE);
  ppyoloe_param.cls = 80;

  printf("setup ppyoloe algorithm param \n");
  ret = CVI_TDL_Set_YOLO_Algparam(tdl_handle, CVI_TDL_SUPPORTED_MODEL_PPYOLOE, ppyoloe_param);
  if (ret != CVI_SUCCESS) {
    printf("Can not set ppyoloe algorithm parameters %#x\n", ret);
    return ret;
  }

  // set thershold
  CVI_TDL_SetModelThreshold(tdl_handle, CVI_TDL_SUPPORTED_MODEL_PPYOLOE, 0.5);
  CVI_TDL_SetModelNmsThreshold(tdl_handle, CVI_TDL_SUPPORTED_MODEL_PPYOLOE, 0.5);

  printf("ppyoloe algorithm parameters setup success!\n");
  return ret;
}

推理代码如下:

ret = CVI_TDL_OpenModel(tdl_handle, CVI_TDL_SUPPORTED_MODEL_PPYOLOE, model_path.c_str());
if (ret != CVI_SUCCESS) {
  printf("open model failed %#x!\n", ret);
  return ret;
}
printf("cvimodel open success!\n");

std::cout << "model opened:" << model_path << std::endl;

VIDEO_FRAME_INFO_S fdFrame;
ret = CVI_TDL_ReadImage(str_src_dir.c_str(), &fdFrame, PIXEL_FORMAT_RGB_888);
std::cout << "CVI_TDL_ReadImage done!\n";

if (ret != CVI_SUCCESS) {
  std::cout << "Convert out video frame failed with :" << ret << ".file:" << str_src_dir
            << std::endl;
}

cvtdl_object_t obj_meta = {0};

CVI_TDL_PPYoloE(tdl_handle, &fdFrame, &obj_meta);

printf("detect number: %d\n", obj_meta.size);
for (uint32_t i = 0; i < obj_meta.size; i++) {
  printf("detect res: %f %f %f %f %f %d\n", obj_meta.info[i].bbox.x1, obj_meta.info[i].bbox.y1,
         obj_meta.info[i].bbox.x2, obj_meta.info[i].bbox.y2, obj_meta.info[i].bbox.score,
         obj_meta.info[i].classes);
}

8.5. 测试结果

测试了ppyoloe_crn_s_300e_coco模型onnx以及cvimodel在cv181x平台的性能对比,其中阈值参数为:

  • conf: 0.01

  • nms: 0.7

  • 输入分辨率:640 x 640

ppyoloe_crn_s_300e_coco模型官方导出方式性能:

测试平台

推理耗时 (ms)

带宽 (MB)

ION(MB)

MAP 0.5

MAP 0.5-0.95

pytorch

N/A

N/A

N/A

60.5

43.1

cv180x

ion分配失败

ion分配失败

29.59

量化失败

量化失败

cv181x

103.62

110.59

14.68

量化失败

量化失败

cv182x

77.58

111.18

14.68

量化失败

量化失败

cv183x

量化失败

量化失败

量化失败

量化失败

量化失败

cv186x

12.35

101.83

18.93

量化失败

量化失败

ppyoloe_crn_s_300e_coco模型的TDL_SDK导出方式性能:

测试平台

推理耗时 (ms)

带宽 (MB)

ION(MB)

MAP 0.5

MAP 0.5-0.95

onnx

N/A

N/A

N/A

55.9497

39.8568

cv180x

ion分配失败

ion分配失败

29.47

ion分配失败

ion分配失败

cv181x

101.15

103.8

14.55

55.36

39.1982

cv182x

75.03

104.95

14.55

55.36

39.1982

cv183x

30.96

80.43

13.8

55.36

39.1982

cv186x

12.29

100.21

19.99

38.67

27.32