fastRCNN

fastRCNN 编译配置

FastRCNN是Ross Girshick在RCNN的基础上增加了Multi task training整个的训练过程和测试过程比RCNN快了许多。别的一些细节不展开,过几天会上传Fast RCNN的论文笔记。FastRCNN mAP性能上略有上升。Fast RCNN中,提取OP的过程和训练过程仍然是分离的。因此我们在训练过程中,需要用OP的方法先把图像OP提取好,再送入Fast RCNN中训练,在检测过程中也是如此需要先把相应的测试图像的OP提取出来送入检测。

首先我要说的是如何安装Fast RCNN环境,具体的流程在Ross Girshick的Github上有,他里面主要是讲解了如何安装和使用。我会稍微提到这一部分内容,主要讲解,如果要训练自己的数据,应该修改那些地方,并把我自己训练的过程跟大家分享一下。

1.当然是Git clone一下Ross的工程啦

这里给出Github的链接https://github.com/rbgirshick/fast-rcnn
首先根据他的提示

Make sure to clone with –recursive
git clone –recursive https://github.com/rbgirshick/fast-rcnn.git

这里不要忘了加–recursive

2.在这里简单介绍一下工程目录

首先工程的根目录简单的称为 FRCN_ROOT,可以看到根目录下有以下几个文件夹

caffe-fast-rcnn

这里是caffe框架目录

data

用来存放pretrained模型 比如imagenet上的,以及读取文件的cache缓存

experiments

存放配置文件以及运行的log文件,另外这个目录下有scripts 用来获取imagenet的模型,以及作者训练好的fast rcnn模型,以及相应的pascal-voc数据集

lib

用来存放一些python接口文件,如其下的datasets主要负责数据库读取 config负责cnn一些训练的配置选项

matlab

放置matlab与python的接口,用matlab来调用实现detection

models

里面存放了三个模型文件,小型网络的CaffeNet 大型网络VGG16 中型网络VGG_CNN_M_1024

output

这里存放的是训练完成后的输出目录,默认会在default文件夹下

tools

里面存放的是训练和测试的Python文件

3.编译Cython module

cd $FRCN_ROOT/lib
make

进入lib目录直接make就可以了

4.编译Caffe and pycaffe

cd $FRCN_ROOT/caffe-fast-rcnn
make -j8 && make pycaffe

这里需要注意的是你直接make -j8 && make pycaffe是会报错的,

可以看到图中是是没有Makefile.config文件,但是作者有一个Makefile.config.example文件,你需要复制它一下然后重命名为Makefile.config

需要注意的是里面还有几个配置需要添加

打开 USE_CUDNN = 1,这个选项默认情况下时关闭的,让CUDA支持DNN

打开 WITH_PYTHON_LAYER = 1,这个在默认情况下也是关闭的,FastRCNN需要支持Python接口,因此需要打开

Fast RCNN需要hdf5的支持,这个根据自己的Linux里的库文件安装路径添加,不清楚的可以find一下,不过一般情况下,INCLUDE_DIRS 应该添加上 /usr/include/hdf5/serial LIBRARY_DIRS 添加上 /usr/lib/x86_x64-linux-gnu/hdf5/serial
另外把USE_PKG_CONFIG = 1 记得打开,要不然会找不到一些库文件,PKG是linux用来管理库文件

这几个是需要在Makefile.config.example中修改的,最好直接copy一个再修改。
另外还有一个需要注意的地方是,当初楼主的linux版本太高,ubuntu这玩意更新太快了,boost库的版本太高,Fast RCNN里面用的是1.55版本的boost库,当时我电脑上是1.59,会出现接口不兼容,记得是废弃了几个接口,编译报错,装回1.55的就可以了

5.下载相应的模型文件

Ross给出的操作是这样的,其实我不推荐这么弄,因为直接用wget去下载的速度比较慢,我们可以打开里面的shell文件,把url粘贴出来,到迅雷里面下载,几分钟就好了

cd $FRCN_ROOT
./data/scripts/fetch_fast_rcnn_models.sh
这里以相应的 imagenet_model为例,你到目录下可以看到3个shell文件,分别是fetch_fast_rcnn_models.s h,fetch_imagenet_models.sh,fetch_selective_search_data.sh,第一是作者训练好的fast_rcnn模型,第二个是imagenet_model上预训练好的模型,第三个对应着的是作者基于Pascal VOC数据集提取的selective_search预选框。如果想要看一下fast rcnn的效果,可以直接加载Ross训练好的fast_rcnn模型,如果要自己训练的话,记得加载imagenet模型

这里是imagenet_model的shell文件,看家里面的URL了没,最后的URL链接就是这个链接再加上FILE变量,链接,你直接把它链接起来,复制到迅雷中下载就可以了,速度灰常快,直接下载的话炒鸡慢啊。
下在之后记得放到data/目录下去解压哦,

6.运行网络和加载模型文件

在tools下面有个demo.py文件

cd $FRCN_ROOT
./tools/demo.py
就可以直接运行,记得看一下里面的参数,这里对显卡有一定的要求,Ross说必须是3G的显存以上才可以跑的动哦,里面有3个大小的网络caffenet是最小的,有显卡应该就能跑起来,vgg_cnn_m_1024是一个中型网络,vgg16是大型网络,后两个得看显卡的显存大小才能跑起,显存不够启动会报错的。

如果在cpu模式下的话速度是灰常慢的,GPU模式下大概0.2秒左右。

对了demo里面都是有显示的函数的,如果你是在linux终端下没有输出设备运行是会报错的

正确运行的结果如下
里面有两个图片检测效果,这里放一张

Fast RCNN训练自己的数据集

讲解了如何修改Fast RCNN训练自己的数据集,首先请确保你已经安装好了Fast RCNN的环境,具体的编配编制操作请参考我的上一篇文章。首先可以看到fast rcnn的工程目录下有个Lib目录
这里下面存在3个目录分别是:
datasets
fast_rcnn
roi_data_layer
utils
在这里修改读写数据的接口主要是datasets目录下,fast_rcnn下面主要存放的是python的训练和测试脚本,以及训练的配置文件,roi_data_layer下面存放的主要是一些ROI处理操作,utils下面存放的是一些通用操作比如非极大值nms,以及计算bounding box的重叠率等常用功能

==修改读写数据的接口主要是datasets目录下,fast_rcnn下面主要存放的是python的训练和测试脚本,以及训练的配置文件,roi_data_layer下面存放的主要是一些ROI处理操作,utils下面存放的是一些通用操作比如非极大值nms,以及计算bounding box的重叠率等常用功能==

构建自己的IMDB子类

datasets目录下主要有三个文件

  • factory.py
  • imdb.py
  • pascal_voc.py

factory.py 学过设计模式的应该知道这是个工厂类,用类生成imdb类并且返回数据库共网络训练和测试使用

imdb.py 这里是数据库读写类的基类,分装了许多db的操作,但是具体的一些文件读写需要继承继续读写

pascal_voc.py Ross在这里用pascal_voc.py这个类来操作

1.2 读取文件函数分析

接下来我来介绍一下pasca_voc.py这个文件,我们主要是基于这个文件进行修改,里面有几个重要的函数需要修改

def init(self, image_set, year, devkit_path=None)
这个是初始化函数,它对应着的是pascal_voc的数据集访问格式,其实我们将其接口修改的更简单一点
def image_path_at(self, i)
根据第i个图像样本返回其对应的path,其调用了image_path_from_index(self, index)作为其具体实现
def image_path_from_index(self, index)
实现了 image_path的具体功能
def _load_image_set_index(self)
加载了样本的list文件
def _get_default_path(self)
获得数据集地址
def gt_roidb(self)
读取并返回ground_truth的db
def selective_search_roidb
读取并返回ROI的db
def _load_selective_search_roidb(self, gt_roidb)
加载预选框的文件
def selective_search_IJCV_roidb(self)
在这里调用读取Ground_truth和ROI db并将db合并
def _load_selective_search_IJCV_roidb(self, gt_roidb)
这里是专门读取作者在IJCV上用的dataset
def _load_pascal_annotation(self, index)
这个函数是读取gt的具体实现
def _write_voc_results_file(self, all_boxes)
voc的检测结果写入到文件
def _do_matlab_eval(self, comp_id, output_dir=’output’)
根据matlab的evluation接口来做结果的分析
def evaluate_detections
其调用了_do_matlab_eval
def competition_mode
设置competitoin_mode,加了一些噪点

训练数据集格式

在我的检测任务里,我主要是从道路卡口数据中检测车,因此我这里只有background 和car两类物体,为了操作方便,我不像pascal_voc数据集里面一样每个图像用一个xml来标注多类,先说一下我的数据格式

修改读取接口

原始初始化函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def __init__(self, image_set, year, devkit_path=None):
datasets.imdb.__init__(self, 'voc_' + year + '_' + image_set)
self._year = year
self._image_set = image_set
self._devkit_path = self._get_default_path() if devkit_path is None \
else devkit_path
self._data_path = os.path.join(self._devkit_path, 'VOC' + self._year)
self._classes = ('__background__', # always index 0
'aeroplane', 'bicycle', 'bird', 'boat',
'bottle', 'bus', 'car', 'cat', 'chair',
'cow', 'diningtable', 'dog', 'horse',
'motorbike', 'person', 'pottedplant',
'sheep', 'sofa', 'train', 'tvmonitor')
self._class_to_ind = dict(zip(self.classes, xrange(self.num_classes)))
self._image_ext = '.jpg'
self._image_index = self._load_image_set_index()
# Default to roidb handler
self._roidb_handler = self.selective_search_roidb

# PASCAL specific config options
self.config = {'cleanup' : True,
'use_salt' : True,
'top_k' : 2000}

assert os.path.exists(self._devkit_path), \
'VOCdevkit path does not exist: {}'.format(self._devkit_path)
assert os.path.exists(self._data_path), \
'Path does not exist: {}'.format(self._data_path)