目录
[1 模型转换(集成nms算子到模型中)](#1 模型转换(集成nms算子到模型中))
[1.1 基础模型说明](#1.1 基础模型说明)
[1.2 模型转换](#1.2 模型转换)
[1.2.1 设置环境变量](#1.2.1 设置环境变量)
[1.2.2 安装yolov5依赖(gcc需要>7.5)](#1.2.2 安装yolov5依赖(gcc需要>7.5))
[1.2.3 转换fp16模型](#1.2.3 转换fp16模型)
[2 模型转换(使用atc,不集成nms算子)](#2 模型转换(使用atc,不集成nms算子))
1 模型转换(集成nms算子到模型中)
1.1 基础模型说明
对于Yolov5模型,华为提供了单独的脚本执行转换,目的通过自定义的Yolov5后处理算子将NMS操作集成到离线模型中,提高推理性能。Yolov5模型转换脚本位于计算库的ascend_yolov5_pt2om,模型转换时使用官方原始yolov5s-v6.1为基础训练的人车非.pt模型,该模型有3个输出。转换工具会自动将3个输出合并为一个输出,并转为onnx模型,之后再转为om模型。默认精度为FP16。
对于INT8,当前转换工具量化后准确率有下降,对于实时性强的场景不适合,暂不使用。
ascend_yolov5_pt2om已上传到csdn资源(你自己的百度网盘里面也有一份)https://download.csdn.net/download/u013171226/89286331?spm=1001.2014.3001.5501
1.2 模型转换
模型转换主要是将.pt模型转为Ascentd可推理的.om模型,包括三种数据类型(fp16、fp32和int8),模型转换过程下。模型转换使用ascend_yolov5_pt2om工程实现。
1.2.1 设置环境变量
bash
source /usr/local/Ascend/ascend-toolkit/set_env.sh
1.2.2 安装yolov5依赖(gcc需要>7.5)
bash
pip install -r requirements.txt
pip install onnx
pip install onnxruntime==1.6.0
pip install onnxsim
pip install opc-tool==0.1.0
pip install decorator
pip install protobuf==3.20.3
pip install numpy
1.2.3 转换fp16模型
bash
bash common/pth2om.sh --version 6.1 --type fp16 --model yolov5_pcb_608_out3 --img_size 608 --class_num 3 --bs 1 --soc Ascend310B1
其中pth2om.sh脚本内容如下,在ascend_yolov5_pt2om文件夹里面有
bash
## 帮助信息
### === Model Options ===
### --version yolov5 tags [2.0/3.1/4.0/5.0/6.0/6.1], default: 6.1
### --model yolov5[n/s/m/l/x], default: yolov5s
### --bs batch size, default: 4
### === Build Options ===
### --type data type [fp16/int8], default: fp16
### --calib_bs batch size of calibration data (int8 use only), default: 16
### === Inference Options ===
### --mode infer/val, default: infer
### --conf confidence threshold, default: 0.4
### --iou NMS IOU threshold, default: 0.5
### --output_dir output dir, default: output
### === Environment Options ===
### --soc soc version [Ascend310/Ascend310P?], default: Ascend310
### === Help Options ===
### -h print this message
help() {
sed -rn 's/^### ?//;T;p;' "$0"
}
## 参数设置
GETOPT_ARGS=`getopt -o 'h' -al version:,model:,img_size:,channel_num:,bs:,class_num:,type:,calib_bs:,mode:,conf:,iou:,output_dir:,soc: -- "$@"`
eval set -- "$GETOPT_ARGS"
while [ -n "$1" ]
do
case "$1" in
-h) help; exit 0 ;;
--version) version=$2; shift 2;;
--model) model=$2; shift 2;;
--img_size) img_size=$2; shift 2;;
--channel_num) channel_num=$2; shift 2;;
--bs) bs=$2; shift 2;;
--class_num) class_num=$2; shift 2;;
--type) type=$2; shift 2;;
--calib_bs) calib_bs=$2; shift 2;;
--mode) mode=$2; shift 2;;
--conf) conf=$2; shift 2;;
--iou) iou=$2; shift 2;;
--output_dir) output_dir=$2; shift 2;;
--soc) soc=$2; shift 2;;
--) break ;;
esac
done
if [[ -z $version ]]; then version=6.1; fi
if [[ -z $model ]]; then model=yolov5s; fi
if [[ -z $img_size ]]; then img_size=608; fi
if [[ -z $channel_num ]]; then channel_num=3; fi
if [[ -z $bs ]]; then bs=4; fi
if [[ -z $class_num ]]; then class_num=3; fi
if [[ -z $type ]]; then type=fp16; fi
if [[ -z $calib_bs ]]; then calib_bs=16; fi
if [[ -z $mode ]]; then mode=infer; fi
if [[ -z $conf ]]; then conf=0.4; fi
if [[ -z $iou ]]; then iou=0.5; fi
if [[ -z $output_dir ]]; then output_dir=output; fi
if [[ -z $soc ]]; then echo "error: missing 1 required argument: 'soc'"; exit 1 ; fi
if [[ ${type} == fp16 ]] ; then
args_info="=== pth2om args === \n version: $version \n model: $model \n bs: $bs \n type: $type \n
mode: $mode \n conf: $conf \n iou: $iou \n output_dir: $output_dir \n soc: $soc"
echo -e $args_info
else
args_info="=== pth2om args === \nversion: $version \n model: $model \n bs: $bs \n type: $type \n calib_bs: $calib_bs \n
mode: $mode \n conf: $conf \n iou: $iou \n output_dir: $output_dir \n soc: $soc"
echo -e $args_info
fi
if [ ! -d ${output_dir} ]; then
mkdir ${output_dir}
fi
## pt导出om模型
echo "Starting 修改pytorch源码"
git checkout . && git checkout v${version}
git apply v${version}/v${version}.patch
echo "Starting 导出onnx模型并简化"
if [[ ${version} == 6* ]] ; then
python3 export.py --weights=${model}.pt --imgsz=${img_size} --batch-size=${bs} --opset=11 --dynamic || exit 1
else
python3 models/export.py --weights=${model}.pt --img-size=${img_size} --batch-size=${bs} --opset=11 --dynamic || exit 1
fi
python3 -m onnxsim ${model}.onnx ${model}.onnx --dynamic-input-shape --input-shape images:${bs},${channel_num},${img_size},${img_size} || exit 1
model_tmp=${model}
if [ ${type} == int8 ] ; then
echo "Starting 生成量化数据"
python3 common/quantize/generate_data.py --img_info_file=common/quantize/img_info_amct.txt --save_path=amct_data --batch_size=${calib_bs} --img_size=${img_size} || exit 1
if [[ ${version} == 6.1 && ${model} == yolov5[nl] ]] ; then
echo "Starting pre_amct"
python3 common/quantize/calibration_scale.py --input=${model}.onnx --output=${model}_cali.onnx --mode=pre_amct || exit 1
echo "Starting onnx模型量化"
bash common/quantize/amct.sh ${model}_cali.onnx || exit 1
if [[ -f ${output_dir}/result_deploy_model.onnx ]];then
mv ${output_dir}/result_deploy_model.onnx ${model}_amct.onnx
fi
rm -rf ${model}_cali.onnx
echo "Starting after_amct"
python3 common/quantize/calibration_scale.py --input=${model}_amct.onnx --output=${model}_amct.onnx --mode=after_amct || exit 1
else
echo "Starting onnx模型量化"
bash common/quantize/amct.sh ${model}.onnx || exit 1
if [[ -f ${output_dir}/result_deploy_model.onnx ]];then
mv ${output_dir}/result_deploy_model.onnx ${model}_amct.onnx
fi
fi
model_tmp=${model}_amct
if [[ -f ${output_dir}/result_* ]];then
rm -rf ${output_dir}/result_result_fake_quant_model.onnx
rm -rf ${output_dir}/result_quant.json
fi
fi
echo "Starting 修改onnx模型,添加NMS后处理算子"
python3 common/util/modify_model.py --pt=${model}.pt --onnx=${model_tmp}.onnx --img-size=${img_size} --class-num=${class_num} --conf-thres=${conf} --iou-thres=${iou} || exit 1
echo "Starting onnx导出om模型(有后处理)"
bash common/util/atc.sh infer ${model_tmp}_nms.onnx ${output_dir}/${model_tmp}_nms ${img_size} ${channel_num} ${bs} ${soc} || exit 1
rm -rf ${model_tmp}_nms.onnx
if [[ ${mode} == val ]] ; then
echo "Starting onnx导出om模型(无后处理)"
bash common/util/atc.sh val ${model_tmp}.onnx ${output_dir}/${model_tmp} ${bs} ${soc} || exit 1
rm -rf ${model_tmp}.onnx
fi
echo -e "pth导出om模型 Success \n"
然后atc.sh脚本内容如下,在ascend_yolov5_pt2om文件夹里面也有
bash
mode=$1
onnx=$2
om=$3
img_size=$4
channel_num=$5
bs=$6
soc=$7
if [ ${mode} == val ];then
input_shape="images:${bs},${channel_num},${img_size},${img_size}"
input_fp16_nodes="images"
elif [ ${mode} == infer ];then
input_shape="images:${bs},${channel_num},${img_size},${img_size};img_info:${bs},4"
input_fp16_nodes="images;img_info"
fi
if [[ ${soc} == Ascend310 ]];then
atc --model=${onnx} \
--framework=5 \
--output=${om}_bs${bs} \
--input_format=NCHW \
--input_shape=${input_shape} \
--log=error \
--soc_version=${soc} \
--input_fp16_nodes=${input_fp16_nodes} \
--output_type=FP16
fi
if [[ ${soc} == Ascend310B1 ]];then
atc --model=${onnx} \
--framework=5 \
--output=${om}_bs${bs} \
--input_format=NCHW \
--input_shape=${input_shape} \
--log=error \
--soc_version=${soc} \
--optypelist_for_implmode="Sigmoid" \
--op_select_implmode=high_performance \
--fusion_switch_file=common/util/fusion.cfg \
--insert_op_conf=aipp_yolov5.cfg
#--input_fp16_nodes=${input_fp16_nodes}
#--output_type=FP16
fi
if [[ ${soc} == Ascend310P? ]];then
atc --model=${onnx} \
--framework=5 \
--output=${om}_bs${bs} \
--input_format=NCHW \
--input_shape=${input_shape} \
--log=error \
--soc_version=${soc} \
--optypelist_for_implmode="Sigmoid" \
--op_select_implmode=high_performance \
--fusion_switch_file=common/util/fusion.cfg \
--insert_op_conf=aipp_yolov5.cfg
#--input_fp16_nodes=${input_fp16_nodes}
#--output_type=FP16
fi
if [[ ${soc} == Ascend710 ]];then
atc --model=${onnx} \
--framework=5 \
--output=${om}_bs${bs} \
--input_format=NCHW \
--input_shape=${input_shape} \
--log=error \
--soc_version=${soc} \
--optypelist_for_implmode="Sigmoid" \
--op_select_implmode=high_performance \
--fusion_switch_file=common/util/fusion.cfg
#--insert_op_conf=aipp_yolov5.cfg
# --insert_op_conf=aipp.cfg
# --insert_op_conf=aipp_yolov5.cfg
fi
if [[ ${soc} == Ascend910 ]];then
atc --model=${onnx} \
--framework=5 \
--output=${om}_bs${bs} \
--input_format=NCHW \
--input_shape=${input_shape} \
--log=error \
--soc_version=${soc} \
--optypelist_for_implmode="Sigmoid" \
--op_select_implmode=high_performance \
--fusion_switch_file=common/util/fusion.cfg
#--insert_op_conf=aipp_yolov5.cfg
# --insert_op_conf=aipp.cfg
# --insert_op_conf=aipp_yolov5.cfg
fi
2 模型转换(使用atc,不集成nms算子)
上述模型转换都是基于.pt文件转换为.om模型文件。另外,还可以直接应用atc工具将onnx模型转为.om模型。
bash
bash common/util/atc.sh infer yolov5_pcb_608_out3_nms.onnx output/yolov5_pcb_608_out3_nms 1 Ascend310B1
或者直接使用atc工具转换
(1)人车非模型
atc --model=yolov5_pcb_608_out3_nms.onnx \
--framework=5 \
--output=yolov5_pcb_608_out3_bs4 \
--input_format=NCHW \
--input_shape="images:1,3,640,640;img_info:1,4" \
--log=error \
--soc_version=Ascend710 \
--optypelist_for_implmode="Sigmoid" \
--op_select_implmode=high_performance
(2)行人结构化模型
atc --model=pedes_structure.onnx \
--framework=5 \
--output=pedes_structure \
--input_format=NCHW \
--input_shape="x:-1,3,224,224" \
--dynamic_batch_size="1,2,4,8" \
--log=error \
--soc_version=Ascend710 \
--optypelist_for_implmode="Sigmoid" \
--op_select_implmode=high_performance