faster-rcnn的训练流程及其如何训练自己的数据集(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_37203756/article/details/79926543

前言:


关于faster rcnn的训练网络,哪怕你一直很努力,死磕代码。就会像这图一样智商不够用啊,这边看了那边忘。所以希望大家能体系的学习faster rcnn。因为走了很多弯路,总结一下自己的理解。本篇关于Faster rcnn 的训练是基于tensorflow版本的,因为最近一直在搞这个,也为了巩固一下知识点,在此写个博客,也希望能帮助到大家。废话不多说,我们直接开始。

第一点:首先要明白faster rcnn目录下都有哪些文件夹,都有什么用处。如下截图:

文件夹:

data--------->存放的是用于训练的数据集,一般我们用的都是voc2007的数据集,知道就行了,还有一个很重要的是文件夹是pretrain_model,必不可少的,这里面存放的VGG_imagenet.npy也就是VGG模型,这个大家在网上找找就能找到。还有一个cache文件夹是随着训练的进行,用来存放训练数据的,为了下次加载数据方便。

experiments---->下面有个scripts文件夹里面存放的是faster_rcnn_end2end.sh,算是起始指令吧,我们是通过运行这个文件,加载参数来调用其他各个文件的。

lib------------>该文件夹里面存放的东西很多,主要是一些python接口文件及运行的log文件。所以说程序运行之前先make一下。关于里面各个作用,下面我会根据训练流程一一讲解。

output-------->存放当然是你的输出结果了,你的训练结束后所训练好的模型。

tools------->里面的是训练、测试的加载起始文件。demo.py是一个简单的测试文件。

好了,关于各个文件的说明已经结束。

第二点:faster rcnn训练流程开始

1.数据加载

通过./experiments/scripts/faster_rcnn_end2end.sh gpu 0  VGG16 pascal_voc命令,调用tools/train_net.py加载完参数后 imdb = get_imdb(args.imdb_name)调用了get_imdb()函数(该函数来于lib/datasets/factory.py)返回的是一个lambda表达式(其实是通过pascal_voc()函数来创建imdb数据的,通过该表达式,进入了pascal_voc函数,初始化了imdb数据,此时,数据加载完成。---->self._roidb_handler = self.gt_roidb并设置了gt_roidb

2.得到最初的roidb数据

然后返回train_net.py函数中执行 roidb = get_training_roidb(imdb)其中要调用imdb.append_flipped_images()函数,这个是基类的imdb的成员函数。在这个函数里面,对所有图像的for循环里,调用了self.roidb()函数(boxes = self.roidb[i]['boxes'].copy()),这个时候就会调用imdb的roidb函数,roidb函数检查类成员_roidb是否为空,如果不是空直接返回,否则调用roidb_db_handler()函数,因已经设了gt_roidb,实际执行了gt_roidb()函数,这个函数是在pascal_voc类。gt_roidb函数通过load_pascal_annotation()读取pascal_voc的标注。形成的roidb格式为:

list[

dict1(for image 1):

{ 'boxes' : (np.array,(N,4),左上角和右下角顶点坐标,从0开始)

  'gt_classes': (np.array,(N,),每个框的类别号,21类--0到20中的数字)

  'gt_overlaps':(np.array,(N,21),稀疏矩阵,每个框对应的那一类为1,其他是0)

  'seg_areas':(np.array,(N,),每个框的面积)

   'flipped':False}

dict2(for image 2):

{

}..................

...]

在这里append_flipped_images就是对每张图片的每个框都做一个水平对称变换(加强数据集),即x坐标变,y坐标不变。最终就是gt_roidb的长度加倍。接着回到get_training_roidb(imdb)函数中,往下执行。由于HAS_RPN=True,IS_MULTISCALE=False.因此调用rdl_roidb(即roi_data_layer文件夹中的roidb文件)的prepare_roidb(imdb)函数,进一步添加roidb数据的字段。)

list[

dict1(for image 1):

{ 'boxes' : (np.array,(N,4),左上角和右下角顶点坐标,从0开始)

  'gt_classes': (np.array,(N,),每个框的类别号,21类--0到20中的数字)

  'gt_overlaps':(np.array,(N,21),稀疏矩阵,每个框对应的那一类为1,其他是0)

  'seg_areas':(np.array,(N,),每个框的面积)

   'flipped':False

    'Image':当前图像的路径

    'width':图像的宽度

    'height':图像的高度

    'max_classes':(np.array,(N,),每个框与gt的overlap最大的类别号,就是类别标号)

    'max_overlaps':(np.array,(N,),全1)}

dict2(for image 2):

{

}..................

...]

小总结:1.2完成后返回了最终的imdb、roidb对象。注意这两部一定要好好结合pascal_voc.py(后续我会继续更新这部分代码的理解)文件进行理解。

3.调用train_net()函数为roidb添加字段

接下来开始真正调用train.py文件中的train_net函数了 roidb = filter_roidb(roidb)roidb要先经过筛选,该函数的作用是删除没有用的roidb数据,具体判决:检查每个图像中至少有一个前景roi(overlap大于0.5)或背景的roi(overlap大于等于0小于0.5),这样imdb和roidb就完全准备好了。开始调用train_net函数。

train_net函数中,需要构造solver对象,而solver类在初始化时需要继续对roidb添加更多的信息,涉及到的函数是self.bbox_means, self.bbox_stds = rdl_roidb.add_bbox_regression_targets(roidb)即rdl_roidb中的add_bbox_regression_targets函数,在该函数中,可以看到为每个图像的roidb中加入了“bbox_targets"字段,调用的函数为_compute_targets(),该函数的输入参数为:

rois :   'boxes' : (np.array,(N,4),左上角和右下角顶点坐标,从0开始)

'max_classes':(np.array,(N,),每个框与gt的overlap最大的类别号,就是类别标号)

'max_overlaps':(np.array,(N,),全1

其实这里调用这个函数没有什么意义。因为这里全是groundtruth的bbox,而这个_compute_targets函数我们稍后会看到它是一个计算回归偏移量的。而gt的bbox传进去,计算的偏移量当然是0。因此可以看到添加的bbox_targets字段是一个(N,5)的矩阵,第一列是类别,后面四列是回归偏移量,在这里全是0。这里只要知道一下被添加了一个字段就好了。下面开始调用solver的train_model函数。


PS:因为内容实在太多,关于下面的训练流程,请看下篇!!!















展开阅读全文

没有更多推荐了,返回首页