天天看点

ssd目标检测训练自己的数据_使用SSD训练自己的数据+源码(pytorch)学习记录(一)

最近的一个任务用到了SSD作检测,将这份代码应用到了自己的数据上,为了防止自己忘了,其中的整个过程作一个记录,同时这两天决定将SSD的源码好好读一遍,加深一下理解。所用的代码地址:

https://github.com/lufficc/SSD​github.com

这份代码是今年的,比起两年前star数量最多的SSD Pytorch实现有更多的灵活度,更详细的文档,作者给出了不同的Backbone,在readme里面给出了特别详细的修改指导,对于想要自己更改网络,写自己的数据类的小伙伴,强烈安利!在此感谢原作者!

因为安装使用SSD和源码解读是很大两块内容,分俩个部分来写,第一部分主要是关于SSD的使用。

SSD安装/训练/推理

安装

:(ubuntu环境)对于如何安装并跑这份代码作者在readme里面写得简直不能太详尽,只补充几个注意点:

  • 养成好习惯,尽量在conda 里面创个虚拟环境
  • CUDA9/10皆可,但是CUDA8是不行的
  • 小Tip: conda install torchvision==0.3.0,一行命令基本帮忙把torch相关依赖都装上了
插播一下数据准备

新建一个datasets文件夹。源码支持coco/voc格式,当然你也可以自定义一个数据接口,这个作者也有指导!自己写数据类请参考ssd/data/datasets/目录下的coco.py和voc.py

对于voc:

--datasets
|   --voc2007
|        --Annotations
|             --1.xml,2.xml,....,......
|        --JPEGImages
|             --1.jpg,2.jpg,....,......
|        --ImageSets
|             --Main
|                 --test.txt #用于测试的。形如1,2,3,4...也就是index 加上.xml或者.jpg就是标签和图像的名字
|                 --train.txt #用于训练的
|                 --trainval.txt #训练加验证
|                 --val.txt #验证
           

仿照VOCDataset(torch.utils.data.Dataset)写一个针对自己特定数据格式的类就可!

对于想自己定义数据类以及更改网络结构的,给出原作者的指导

https://github.com/lufficc/SSD/blob/master/DEVELOP_GUIDE.md​github.com

含有三个目标的voc格式的.xml文件标长这样:

ssd目标检测训练自己的数据_使用SSD训练自己的数据+源码(pytorch)学习记录(一)
训练

  • 组织好数据后,需要把它的路径写到 ssd/config/path_catlog.py中,同时在configs/vgg_ssd300voc0712.yaml文件中指定所用数据。为了方便,上面我直接把自己的数据就命名为VOC2007,这样其实不需要改 pathcatlog.py.
ssd目标检测训练自己的数据_使用SSD训练自己的数据+源码(pytorch)学习记录(一)

如果按照VOC命名则不需要更改,只是给出它和下面图中yaml的对应关系

  • 还有一个特别需要注意的点就是类别的更改,在default.py和,.yaml中的NUM_CLASSES是自己的数据的类别,记得加上背景,同时,一定要在voc.py或者coco.py中(如果用的voc/coco格式)将类别标签都改为自己的
  • 运行train.py的训练的时候,由于在ssd/config/default.py中,默认是vgg网络作为backbone,但是如果你选择了使用预训练模型,那么往往会遇到一个问题,预训练模型需要到程序中指定的那个url去下载,但往往会失败。所以,这个时候不如到网上找一个vgg16的预训练模型vgg16_reducedfc.pth,根据错误提示,把模型放到~/.torch/models/下面,要在命令行下面操作,.torch是隐藏文件,图形界面找不到的!
接下来是对里面的几个关键文件作一个说明: ssd/config/defaults.py和 configs/vgg_ssd300_voc0712.yaml:

这两个是都是这个工程的参数配置,yaml比前者的优先级高,yaml没有的到defaults里面找,使用何种backbone,输入图片大小,特征图,默认框的生成配置,训练配置等等都在里面。几个关键的点:

更换backbone:

这个对应了defaults.py中的# Backbone部分,在ssd/modeling/backbone目录下面可以看到,作者提供了三个backbone。但是并非简简单单的把_C.MODEL.BACKBONE.NAME = 'vgg'换成mobilenet或者efficientnet就可。前面的链接里面作者也给出了指导:

ssd目标检测训练自己的数据_使用SSD训练自己的数据+源码(pytorch)学习记录(一)

但是问题来了,这几个参数该咋改呢,咋知道mobilenet对应的几个特征图的输出通道和大小呢?当然只能去看在ssd/modeling/backbone目录下面的源码了,以下对于更换为mobilenet的情况作一个说明。源码支持300和512大小的图像输入,对于300x300的输入,尝试着自己打印一下作者定义的mobilenet为基础的banckbone的网络就很容易得到各个特征图的信息:

torch.Size([2, 96, 19, 19])
torch.Size([2, 1280, 10, 10])
torch.Size([2, 512, 5, 5])
torch.Size([2, 256, 3, 3])
torch.Size([2, 256, 2, 2])
torch.Size([2, 64, 1, 1])
#输出通道分别是[96,1280,512,256,256,64]
#大小分别是[19,10,5,3,2,1]
#STRIDES代表了特征图框放大到原始图的缩放比例,输入图像是300x300,
#那么300除以各个特征图的大小就对应了比例:[15,30,60,100,150,300]
对于不能整除的情况,可以近似(这一点其实我也不是特别的理解,
我觉得完全可以在设计网络阶段就把其全都设计为整除的啊)
           

插播一句:

_C
           

所以更改后:

(注意一定要把mobilenet名字写全,看源码里面叫啥:是叫mobilenet_v2啊!!!!!!)

ssd目标检测训练自己的数据_使用SSD训练自己的数据+源码(pytorch)学习记录(一)

顺便给出imgesize=512对应的vgg和mobilenet_v2的特征图size信息

512输入对应的vgg的六个FeatureMap
torch.Size([2, 512, 64, 64])
torch.Size([2, 1024, 32, 32])
torch.Size([2, 512, 16, 16])
torch.Size([2, 256, 8, 8])
torch.Size([2, 256, 6, 6])
torch.Size([2, 256, 4, 4])

512输入对应的mobilenet_v2的六个FeatureMap
torch.Size([2, 96, 32, 32])
torch.Size([2, 1280, 16, 16])
torch.Size([2, 512, 8, 8])
torch.Size([2, 256, 4, 4])
torch.Size([2, 256, 2, 2])
torch.Size([2, 64, 1, 1])
           

至于lr,batch_size,模型输出路径等到.yaml中修改

推理

参考:demo.py

补充说明,源码中是用的vizer库在绘图,但是我感觉这给绘出来的图太细了,而且不支持中文显示,我没搞懂怎么调,于是用cv2和PIL重新写了一遍

附上linux下中文字体的路径:

/usr/share/fonts/truetype/arphic/uming.ttc
           
数据增强

可参考:

lim0:目标检测数据集的增强(旋转,镜像,亮度等)含针对VOC标注格式数据的源码​zhuanlan.zhihu.com

ssd目标检测训练自己的数据_使用SSD训练自己的数据+源码(pytorch)学习记录(一)
下一步的计划

对于SSD源码的解读放在下篇

继续阅读