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找到下图对应的文件夹:

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 |