1.NaonoDet模型简介
NanoDet是一个速度超快和轻量级的移动端Anchor-free目标检测模型,该模型的模型文件大小仅几兆(nanodet_m.pth仅3.86M),其在移动ARM CPU上的速度达到97fps(10.23ms),而且提供了基于ncnn推理框架的C++实现和Android demo。本次项目我们基于PyTorch来实现使用NanoDet模型进行车辆检测。
2.模型环境搭建
2.1源码下载
NanoDet的源码已经在GitHub开源社区中公布,我们在GitHub中搜索找到NanoDet的源码,源码地址:https://github.com/RangiLyu/nanodet;下载并解压到本地。打开nanodet文件夹中的requirement.txt文件夹,查看需要的环境配置,如下图所示:
打开cmd界面进入之前配置好的虚拟环境中,通过指令conda list查看已经安装的Python库,由于之前我们已经安装好了torch和torchvision,并且torch版本高于1.6,所以这里不需要重新安装。需要注意的是,torch 1.7版本之前不支持分布式训练,所以在选择安装torch版本的时候尽量高于1.7版本。
2.2 Pycocotools的安装与配置
我们在安装库文件的过程中,比较难安装的库主要是Pycocotools。由于Pycocotools的开发者并没有考虑在Windows环境中的适配,所以我们直接通过pip指令进行安装时会报错,但是GitHub中已有开发者修改出了Windows环境中的Pycocotools,所以可以直接拿来使用。源码地址为:https://github.com/philferriere/cocoapi,根据教程在命令行输入:
pip install git+https://github.com/philferriere/cocoapi.git#subdirectory=PythonAPI
安装成功。参考博客:Windows环境下的pycocotools安装
2.3NanoDet测试
在pycocotools安装成功后,使用pip指令将剩余的库安装完毕,开始对nanodet进行测试,检查是否能正常运行。这里我们使用pytorch的demo程序进行测试,测试之前需要下载预训练权重文件,根据教程中需要在谷歌云盘中下载,下载地址为:https://drive.google.com/file/d/1ZkYucuLusJrCb_i63Lid0kYyyLvEiGN3/view。将预权重文件下载下来后,在nanodet-main中新建文件夹model,将权重文件放入其中。
在命令行输入:
python demo/demo.py webcam --config ./config/nanodet-m.yml --model ./model/nanodet_m.pth --camid 0
查看是否能正常调用摄像头,结果出现报错,如下图所示:
经过查找报错内容,找出报错原因是numpy库版本太低造成的,通过升级numpy即可解决,在命令行输入:
pip install --upgrade numpy
安装结束后再次调用摄像头,正常运行,如下图所示:
3.数据测试和结果
3.1数据集的准备与源码修改
NanoDet支持voc和coco两种格式的训练,这里我们使用coco格式进行训练。我们进入一个开源数据集网站:https://public.roboflow.com/object-detection,在里面寻找合适的数据集,这里我们选用车辆数据集进行训练。我们选取coco json格式的数据集下载下来,进行后续的数据集准备。
在NanoDet的项目文件下新建文件夹coco,用于存放数据集,数据集目录结构如下图所示:
其中annotations文件夹用于存放数据集的标签json文件,test文件夹用于存放用于测试的图片集,train2017存放用于训练的图片集,val2017存放用于验证的图片集,到这里数据集的准备工作就完成了。
接下来修改配置文件,修改的文件为config/nanodet-m.yml,按照需求修改以下几处:
num_classes为数据类别,这里的车辆数据集数据类别修改为5;
Img_path和ann_path分别为训练集图片路径和标签集路径;inout_size为输入图片大小,我们使用的数据集图片尺寸为412*412;
Worker_per_gpu修改为2,这里数值过大会造成爆内存,batchsize_per_gpu修改为16,这里的数值过小,在训练过程中会造成梯度爆炸,损失值直接全部为nan,这里我们通过调大这个数值来避免这种情况;
Total_epochs为训练集训练次数,这里改为100;val_intervals为验证集训练次数,这里改为25,;interval为打印间隔时间,这里修改为10;class_names为数据集类别名称,我们选用的数据集有五个类别,分别为’Ambulance’, ‘Bus’, ‘Car’, ‘Motorcycle’, ‘Truck’。
至此我们的数据集准备和源码修改就结束了,接下来就可以对数据集进行训练了。
3.2训练数据集
在命令行输入
python tools/train.py config/nanodet-m.yml`
开始训练数据集,这时出现报错,如下图所示:
通过查看报错内容,报错原因可能是Windows上并不支持nccl导致的,解决办法是不使用tools文件中的train.py进行训练,我们使用tools/deprecated/文件下的train.py文件进行训练,这时报错消失,数据集开始训练,训练过程如下图所示:
训练结束时又报错了,报错内容为:
TypeError: 'numpy.float64' object cannot be interpreted as an integer
这里有两种解决办法,一种是降低numpy版本,另一种是修该源码,具体操作可见博客:训练数据出现TypeError: ‘numpy.float64’ object cannot be interpreted as an integer错误
我使用第二种办法解决了,因为我的numpy版本为1.20,降低版本还是会报错…
3.3推断测试
数据集训练结束后会生成两个权重文件,这里我们选用model_best.pth文件进行推断测试,在命令行输入:
python demo/demo.py image --config ./config/nanodet-m.yml --model ./model/model_best.pth --path ./coco/test
对coco文件夹下的test测试文件夹内的图片进行测试,部分测试结果如下图所示:
由于NanoDet模型源码在使用demo.py程序对视频进行检测时,检测生成的视频文件无法打开,所以这里就不再对视频进行推断测试。
4.结果分析
通过对推断测试的结果进行观察和分析,可以看出大部分的车辆都能被准确识别,但是对于远处小目标的检测以及车身不完整的目标会出现漏检的情况,检测精度会下降。相对于YOLOv5模型,NanoDet模型在数据集相同、epoch次数相同的情况下训练过程更短,训练生成的权重文件也更小,更有利于部署在手机、车辆等便携移动平台上。
NanoDet模型对Windows的环境并不友好,推荐使用Linux来跑,坑会少一些。