基于CenterNet目标检测的算法移植与测试

课程全程将在SOPHGO(算能)云平台上进行。

本次课程将介绍:

1. SOPHGO(算能)云平台环境搭建

2. CenterNet目标检测算法

3. 通过BMNNSDK进行CenterNet网络模型转换和量化

4. 实现算法的移植

5. 部署和测试

6. 相关链接

1. SOPHGO(算能)云平台环境搭建

 1.1. 开通云平台账号

注意:申请开通BM1684-PCIE通用云开发空间

参考:https://cloud.sophgo.com/tpu.pdf

1.2. 开发环境初始化

1.2.1 进入命令行模式,进去默认在/home/sophgo目录

 

1.2.2 切换成 root 权限


sudo -i
 

1.2.3 安装驱动


cd /home/sophgo/bmnnsdk2-bm1684_v2.7.0/scripts
./install_driver_pcie.sh
ls /dev/bm*

如果可以看到以下设备节点,表示驱动安装成功:

 

1.2.4 加载Docker,并初始化环境


cd /home/sophgo/
apt install unzip
unzip bmnnsdk2-bm1684-ubuntu-docker-py37.zip
cd bmnnsdk2-bm1684-ubuntu-docker-py37/
docker load -i bmnnsdk2-bm1684-ubuntu.docker
 

1.2.5 通过脚本创建Docker容器


cd /home/sophgo/bmnnsdk2-bm1684_v2.7.0/
# 执行脚本创建Docker容器
./docker_run_bmnnsdk.sh

# 自动进入Docker容器
# 进行环境初始化
cd scripts/

# 更新 pip
/usr/local/bin/python3 -m pip install --upgrade pip

# 安装 nntc
./install_lib.sh nntc

# 执行脚本 envsetup_pcie.sh 设置环境变量
source ./envsetup_pcie.sh

# 安装sophon包
pip3 install /workspace/lib/sail/python3/pcie/py37/sophon-2.7.0-py3-none-any.whl
 

1.2.6 Docker 常用命令


# 启动 Docker容器
docker start <CONTAINER ID>

# 查看正在运行的 Docker容器
docker ps

# 进入 Docker 容器 docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
docker exec -it <CONTAINER ID> bash
 


1.2.7 通过云空间文件系统拷贝代码到Docker容器中

打开云空间文件系统:

 

上传文件:文件会被存储在服务器的 /tmp 目录下

 

拷贝文件到Docker容器中:
Docker容器的workspace目录被映射到 /home/sophgo/bmnnsdk2-bm1684_v2.7.0/


cp /tmp/<待拷贝文件> /home/sophgo/bmnnsdk2-bm1684_v2.7.0/
 

注意:本教程后续步骤均在Docker容器中进行

2. CenterNet目标检测算法

论文链接:https://arxiv.org/abs/1904.07850

代码仓库链接:https://github.com/xingyizhou/CenterNet

CenterNet是在2019年论文Objects as points中提出,相比yolo,ssd,faster_rcnn依靠大量anchor的检测网络,CenterNet是一种anchor-free的目标检测网络,在速度和精度上都比较有优势,可以实现:

  • 二维目标检测
  • 三维目标检测
  • 关键点检测

3. 模型的转换和量化

3.1 准备模型与数据

 从Github上获取SOPHON示例项目:git clone -b 2.7.0 https://github.com/sophon-ai-algo/examples.git

3.1.1 获取主干网的预训练模型

运行如下命令下载 dlav0 作为主干网的预训练模型:


apt update
apt install curl
cd ${centernet}/data/scripts
# 下载 ctdet_coco_dlav0_1x.pth 模型文件到路径 ${centernet}/data/bulid 目录下
./download_pt.sh
 

3.1.2 将训练好的Pytorch模型转换为JIT模型
由于BMNNSDK中的PyTorch模型编译工具BMNETP只接受PyTorch的JIT模型(TorchScript模型),需要用户自行将训练好的Pytorch模型进行转换。

JIT(Just-In-Time)是一组编译工具,用于弥合PyTorch研究与生产之间的差距。它允许创建可以在不依赖Python解释器的情况下运行的模型,并且可以更积极地进行优化。在已有PyTorch的Python模型(基类为torch.nn.Module)的情况下,通过torch.jit.trace就可以得到JIT模型,如torch.jit.trace(python_model, torch.rand(input_shape)).save('jit_model')。BMNETP暂时不支持带有控制流操作(如if语句或循环)的JIT模型,因此不能使用torch.jit.script,而要使用torch.jit.trace,它仅跟踪和记录张量上的操作,不会记录任何控制流操作。

从Github上获取CenterNet源码:git clone https://github.com/xingyizhou/CenterNet.git

其中${centernet}/data/bulid/dlav0.py为修改CenterNet源码的dlav0.py的DLASeg类forward方法的返回值得到的。目的是为了将heatmap, wh, reg三个head的特征图concat到一起,固定bmodel输出顺序:


...
return torch.cat((ret['hm'], ret['wh'], ret['reg']), 1)
...
 

导出PyTorch的JIT模型(TorchScript)模型

cd ${centernet}/data/bulid
python3 export.py
# 拷贝生成的 ctdet_coco_dlav0_1x.torchscript.pt 到路径 ${centernet}/data/models 下
cp ctdet_coco_dlav0_1x.torchscript.pt ../models
# 输出:
[DEBUG]arch is: dlav0
loaded ctdet_coco_dlav0_1x.pth, epoch 140
ctdet_coco_dlav0_1x.torchscript.pt exported


3.2 生成FP32 BModel

BMNETP是针对pytorch的模型编译器,可以把pytorch模型直接编译成BMRuntime所需的执行指令。https://doc.sophgo.com/docs/2.7.0/docs_latest_release/nntc/html/usage/bmnetp.html

方式一(推荐):执行以下脚本,使用bmnetp编译生成FP32 BModel:


cd ${centernet}/data/scripts
./1_gen_fp32bmodel.sh

上述脚本会在${centernet}/data/models文件夹下根据ctdet_coco_dlav0_1x.torchscript.pt生成ctdet_coco_dlav0_1output_512_fp32_1batch.bmodel文件,即转换好的FP32 BModel。

方式二:通过以下命令可以实现FP32 BModel模型的直接生成(如需完成后续步骤请将生成的模型拷贝至${centernet}/data/models路径下):

python3 -m bmnetp \
    --net_name=ctdet_dlav0 \
    --target=BM1684 \
    --opt=2 \
    --cmp=true \
    --enable_profile=true \
    --shapes=[1,3,512,512] \
    --model=${ctdet_coco_dlav0_1x.torchscript.pt所在路径} \
    --outdir=${输出的文件夹路径} \
    --dyn=false
 

3.3 生成INT8 BModel


不量化模型可跳过本节。

3.3.1 准备量化集
量化集使用COCO Detection 2017的验证集 我们选取其中的200张图片进行量化
通过运行脚本获得数据:

# 进行下载前确保Docker中已安装unzip
apt install unzip
# 下载图片至 ${centernet}/data/image 目录下
cd ${centernet}/data/scripts
./00_prepare.sh
 

3.3.2 量化生成INT8 BModel

INT8 BModel的生成需要经历中间格式UModel,即:原始模型→FP32 UModel→INT8 UModel→INT8 BModel。

执行以下命令,将依次调用以下步骤中的脚本(参考3.3.3 - 3.3.6),生成INT8 BModel:


./2_gen_int8bmodel.sh
# 转换成功后,模型位于../models/ctdet_coco_dlav0_1output_512_int8_4batch.bmodel
 

3.3.3 生成LMDB

需要将原始量化数据集转换成lmdb格式,供后续校准量化工具Quantization-tools 使用。更详细信息请参考:[准备LMDB数据集](https://doc.sophgo.com/docs/docs_latest_release/calibration-tools/html/module/chapter4.html#lmdb)。

在docker开发容器中使用ufw.io 工具从数据集图片生成LMDB文件,具体操作参见convert_imageset.py, 相关操作已被封装在 scripts/20_create_lmdb.sh中,执行如下命令即可:


./20_create_lmdb.sh
 

上述脚本会在${centernet}/data/images/中生成data.mdb的文件
请注意根据模型输入要求修改脚本中convert_imageset命令中的resize_width和resize_height等参数。

3.3.4 生成FP32 UModel

执行以下命令,使用ufw.pt_to_umodel生成FP32 UModel,若不指定-D参数,可以在生成prototxt文件以后修改:


./21_gen_fp32umodel.sh

上述脚本会在`${centernet}/data/build/int8model/`下生成*_bmnetp_test_fp32.prototxt、*_bmnetp.fp32umodel文件,即转换好的FP32 UModel。

3.3.5 修改FP32 UModel

执行以下命令,修改FP32 UModel的prototxt文件即ctdet_coco_dlav0_1x.torchscript_bmnetp_test_fp32.prototxt,将输入层替换为Data层指向LMDB文件位置(若上一步已经指定-D参数,则无需操作),并使用transform_op完成需要进行的预处理;对于CenterNet来说,需要设置scale;如果transform_op无法完成要求的预处理,那么可以使用Python程序来生成LMDB文件:


./22_modify_fp32umodel.sh
 

3.3.6 生成INT8 UModel

执行以下命令,使用修改后的FP32 UModel文件生成INT8 UModel:


./23_gen_int8umodel.sh
 

上述脚本会在${centernet}/data/build/int8model/下生成*_bmnetp_deploy_fp32_unique_top.prototxt、*_bmnetp_deploy_int8_unique_top.prototxt和*_bmnetp.int8umodel文件,即转换好的INT8 UModel。

3.4 查看BModel的信息

命令:bm_model.bin --info xxxx.bmodel

cd ${centernet}/data/models
# 查看模型信息
bm_model.bin --info ctdet_coco_dlav0_1output_512_fp32_1batch.bmodel
# 得到以下输出
bmodel version: B.2.2
chip: BM1684
create time: Mon Sep  5 06:49:03 2022

==========================================
net 0: [ctdet_dlav0]  static
------------
stage 0:
input: input.1, [1, 3, 512, 512], float32, scale: 1
# 其中第二维是84,concat了热力图、宽高、偏移输出
output: 40, [1, 84, 128, 128], float32, scale: 1

device mem size: 113864072 (coeff: 72048648, instruct: 134528, runtime: 41680896)
host mem size: 0 (coeff: 0, runtime: 0)

cd ${centernet}/data/models
# 查看模型信息
bm_model.bin --info ctdet_coco_dlav0_1output_512_int8_4batch.bmodel
# 得到以下输出
bmodel version: B.2.2
chip: BM1684
create time: Tue Sep  6 01:55:48 2022

==========================================
net 0: [ctdet_coco_dlav0_1x.torchscript_bmnetp]  static
------------
stage 0:
input: input.1, [4, 3, 512, 512], int8, scale: 71.5776
output: 40, [4, 84, 128, 128], float32, scale: 1

device mem size: 89838272 (coeff: 30114112, instruct: 180608, runtime: 59543552)
host mem size: 0 (coeff: 0, runtime: 0)
 

4. 实现算法移植

4.1 Python示例程序: 

目录路径:${centernet}/py_bmcv_sail
 

4.2 C++示例程序: 


目录路径:${centernet}/cpp_bmcv_sail
 

5. 部署和测试

5.1 Python示例程序部署测试

Python代码无需编译,可以直接运行

由于python例程需要用到sail库:


# 在容器里, 以python3.7的docker为例
cd /workspace/lib/sail/python3/pcie/py37
pip3 install sophon-2.7.0-py3-none-any.whl

注:在Docker容器中注意环境变量的设置(参考1.2.5设置环境变量)



cd ${centernet}/py_bmcv_sail

# 1batch
python3 det_centernet_bmcv_sail_1b_4b.py --bmodel=../data/models/ctdet_coco_dlav0_1output_512_fp32_1batch.bmodel --input=../data/ctdet_test.jpg
# 执行完毕后,在当前目录生成ctdet_result_20xx-xx-xx-xx-xx-xx_b_x.jpg格式的图片
# 图片上检测出11个目标

# 4batch
python3 det_centernet_bmcv_sail_1b_4b.py --bmodel=../data/models/ctdet_coco_dlav0_1output_512_int8_4batch.bmodel --input=../data/ctdet_test.jpg
# 执行完毕后,在当前目录生成ctdet_result_20xx-xx-xx-xx-xx-xx_b_x.jpg格式的图片
# 按照量化结果差异,图片上检测出11-13个目标,均属正常范围
 

5.2 C++示例程序部署测试


5.2.1  编译


$ cd ${centernet}/cpp_bmcv_sail
# 先手动修改Makefile.pcie里的top_dir地址,指向实际SDK的根路径
# docker容器中,默认为/workspace
$ make -f Makefile.pcie # 生成centernet_bmcv_sail.pcie

5.2.2  运行测试C++程序


# 1batch
$ ./centernet_bmcv_sail.pcie --bmodel=../data/models/ctdet_coco_dlav0_1output_512_fp32_1batch.bmodel --image=../data/ctdet_test.jpg
# 执行完毕后,在当前目录生成ctdet_result_20xx-xx-xx-xx-xx-xx.jpg格式的图片
# 图片上检测出11个目标

# 4batch
$ ./centernet_bmcv_sail.pcie --bmodel=../data/models/ctdet_coco_dlav0_1output_512_int8_4batch.bmodel --image=../data/ctdet_test.jpg
# 执行完毕后,在当前目录生成ctdet_result_20xx-xx-xx-xx-xx-xx-bx.jpg格式的图片
# 按照量化结果差异,图片上检测出11-12个目标,均属正常范围
 


5.3 获得推理生成的图片


*注意:由于是在Docker容器中,如果想要看到推理的可视化结果需要退出容器,并打开Docker容器映射的文件夹,在对应位置将图片拷贝到 /tmp 文件夹下后可在云平台文件系统中下载。


# 退出容器
exit
# 进入Docker容器映射的文件夹,即Docker容器中的 workspace/目录
cd /home/sophgo/bmnnsdk2-bm1684_v2.7.0/

# 打开centernet项目, ${centernet}即项目所在路径
# 以python测试结果为例
cd ${centernet}/py_bmcv_sail

# 拷贝需要的推理结果图片
cp ctdet_result_20xx-xx-xx-xx-xx-xx_b_x.jpg /tmp/

云空间文件系统:

 测试结果展示:

 

6. 相关链接

样例开源仓库:https://github.com/sophon-ai-algo/examples

BM1684 BMNNSDK文档:https://developer.sophgo.com/site/index/document/6/all.html

编译工具用户开发手册: https://doc.sophgo.com/docs/2.7.0/docs_latest_release/nntc/html/index.html

量化工具用户开发手册: https://doc.sophgo.com/docs/2.7.0/docs_latest_release/calibration-tools/html/index.html

算能量化工具介绍及使用说明:https://www.bilibili.com/video/BV1DA4y1S75p?spm_id_from=333.999.0.0

官网视频教程:https://developer.sophgo.com/site/index/course/all/all.html

官网文档中心:https://developer.sophgo.com/site/index/document/all/all.html

官网下载中心:https://developer.sophgo.com/site/index/material/all/all.html

官网论坛:https://developer.sophgo.com/forum/view/43.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值