题目是目标,我们先一步一步来做,第一步是训练神经网络, 我用的是 kitti 数据集,训练顺序为,第一步,拿到kitti数据集,第二步,把kitti数据集修改为voc数据集格式,第三步,修改配置文件进行训练
关于前两步,是copy自
他这个转xml的脚本稍微改改路径就可以直接运行了,然后就是训练,修改一下配置文件即可开始训练,参考我写的笔记
nanodet训练voc数据集_zhqh100的博客-CSDN博客_nanodet 训练voc
我就不全粘贴了,只粘贴一小部分配置文件
num_classes: 4
...
num_classes: 4
...
class_names: &class_names ['Car', 'Pedestrian', 'Cyclist', 'Truck']
....
img_path: /home/luke/Download/kitti_object/training/train/image_2 #Please fill in train image path
ann_path: /home/luke/Download/kitti_object/training/train/Annotations #Please fill in train xml path
...
img_path: /home/luke/Download/kitti_object/training/train/image_2 #Please fill in val image path
ann_path: /home/luke/Download/kitti_object/training/test/Annotations #Please fill in val xml path
上面的test,就是把train的一部分Annotations的xml文件,移动到test目录即可
mv *9.xml ../test
然后就是训练完毕了,然后跑一下demo,看看效果
python demo/demo.py --config config/nanodet_custom_xml_dataset.yml --model workspace/nanodet_m/model_best/nanodet_model_best.pth --path ~/Download/study/xcjly.mp4
效果满意了,那下一步,先把这个ncnn的项目跑通,因为他这个demo本来使用coco数据集的,跟我们这个kitti数据集肯定有一些区别
最核心的是,coco数据集有80个分类,而kitti数据集只有4分类
main.cpp里需要修改两个地方
const int color_list[4][3] =
{
//{255 ,255 ,255}, //bg
{216 , 82 , 24},
{236 ,176 , 31},
{125 , 46 ,141},
{118 ,171 , 47}
};
static const char* class_names[] = { "Car", "Pedestrian", "Cyclist", "Truck"};
nanodet.h需要修改几个地方
int input_size[2] = {320, 320};
int num_class = 4;
std::vector<std::string> labels{"Car", "Pedestrian", "Cyclist", "Truck"};
因为我配置文件里是input_size: [320,320],所以我这里也要相应的修改
编译的话,应该没啥太大的问题,我这里还是罗嗦一下,从 https://github.com/Tencent/ncnn/releaseshttps://github.com/Tencent/ncnn/releases
解压缩到 demo_ncnn 目录, CMakeLists.txt中稍微修改一下,
find_package(ncnn REQUIRED PATHS ncnn-20220216-ubuntu-2004-shared)
嗯,好像还没说怎么生成ncnn的参数文件,首先生成onnx文件,
python tools/export_onnx.py --cfg_path config/nanodet_custom_xml_dataset.yml --model_path workspace/nanodet_m/model_best/nanodet_model_best.pth
那就会生成 nanodet.onnx 文件,
然后把这个onnx文件,复制到上面的 ncnn-20220216-ubuntu-2004-shared/bin 目录下,运行
./onnx2ncnn nanodet.onnx nanodet.param nanodet.bin
就可以生成ncnn的库文件,然后复制到编译好的 nanodet_demo 目录下,运行
./nanodet_demo 2 ~/Download/study/xcjly.mp4
速度还是挺快的,差不多130fps
下面,我们干一件反过来的事儿,还是用onnx也运行起来,当然这一步也可以不做,看兴趣
用onnx运行nanodet,就不是一两句话就能说明白的了,我新建了一个工程
https://github.com/moneypi/Nanodet_ONNX_demohttps://github.com/moneypi/Nanodet_ONNX_demo到如下官方下载最新版本的运行库,然后复制解压缩,稍微修改一下路径,编译即可运行https://github.com/microsoft/onnxruntime/releases
https://github.com/microsoft/onnxruntime/releases
我上传的时候,就是从jetson上上传的,我的默认库就是arm64的库,也就是说代码如果放到PC机上,用onnxruntime x64的库即可运行,如果放到jetson上,换为 onnxruntime linux aarch64 的库就可以正常运行了,只不过,速度确实挺慢的,inference 146ms, total差不多是176ms
用tensorrt的推理,我也已合并完成,代码已上传至 https://github.com/moneypi/Nanodet_tensorrt_demohttps://github.com/moneypi/Nanodet_tensorrt_demo
推理速度为 23ms, 总耗时差不多 52ms,不过目前比较疑惑的一个问题是,我还是无法把onnx完全转为int8模型,即使我用下面命令也不行
/usr/src/tensorrt/bin/trtexec --onnx=nanodet.onnx --saveEngine=nanodet_int8.trt --int8
即使加上 --noTF32 参数也不行,我发展转几个格式之后,参数量都没有明显的减少,速度也没有明显的提升,基本上跟fp32一致,我还是需要再研究研究
jetson@jetson-desktop:~/Downloads/demo_tensorrt/build$ ls -lh nanodet*.trt
-rw-rw-r-- 1 jetson jetson 4.2M 3月 31 17:03 nanodet_fp16.trt
-rw-rw-r-- 1 jetson jetson 4.1M 3月 31 16:55 nanodet_fp32.trt
-rw-rw-r-- 1 jetson jetson 6.3M 3月 31 18:16 nanodet_int8.trt
-rw-rw-r-- 1 jetson jetson 4.2M 3月 31 17:41 nanodet.trt
但是他这个应该是tensorrt 7 的代码,我修改了一下, 可以用tensorrt8转成功
# build trt engine
builder.max_batch_size = max_batch_size
- builder.max_workspace_size = 1 << 30 # 1GB
- builder.fp16_mode = fp16_mode
+ # profile = builder.create_optimization_profile()
+ config = builder.create_builder_config()
+ # config.add_optimization_profile(profile)
+ config.max_workspace_size = 1 << 32
+
+
+ # builder.max_workspace_size = 1 << 30 # 1GB
+ # builder.fp16_mode = fp16_mode
if int8_mode:
- builder.int8_mode = int8_mode
+ config.set_flag(trt.BuilderFlag.INT8)
+ # builder.int8_mode = int8_mode
assert calibration_stream, 'Error: a calibration_stream should be provided for int8 mode'
- builder.int8_calibrator = Calibrator(calibration_stream, calibration_table_path)
+ config.int8_calibrator = Calibrator(calibration_stream, calibration_table_path)
print('Int8 mode enabled')
- engine = builder.build_cuda_engine(network)
+ elif fp16_mode:
+ config.set_flag(trt.BuilderFlag.FP16)
+ # engine = builder.build_cuda_engine(network)
+ engine = builder.build_engine(network, config)
if engine is None:
但是推理的时候又报错了
[04/01/2022-14:48:45] [E] Error[6]: The engine plan file is generated on an incompatible device, expecting compute 5.3 got compute 7.5, please rebuild.
[04/01/2022-14:48:45] [E] Error[4]: [runtime.cpp::deserializeCudaEngine::50] Error Code 4: Internal Error (Engine deserialization failed.)
[04/01/2022-14:48:45] [E] Failed to create engine from model.
[04/01/2022-14:48:45] [E] Engine set up failed
网上说要用相同的GPU来生成模型文件,难道要我放到jetson nano上运行再生成吗?
__________________________________________
今天还是试了一下原工程中的ncnn的demo,放到jetson nano上,单帧速度差不多是78ms,ncnn从 Releases · Tencent/ncnn · GitHub下载ncnn-20220216-full-source.zip ,参考编译步骤
不过我这里还是报错:
set_vulkan_compute failed, network use_vulkan_compute disabled
这个错误是因为在ssh登录的时候才报的,如果是jetson nano,连上显示器,图形界面直接运行,就不会报,而且,单帧的推理时间大概是32ms,总运算速度为每帧48ms,居然比 tensorrt 还快
然后,我参考官方文档,进行量化,
然后重新推理时,报错
set_vulkan_compute failed, network use_vulkan_compute disabled
嗯,跟上面一样,而且上面的办法解决不了,单帧推理速度达到了110ms,还不如不量化