目录
运行代码
代码分析
运行代码
原作者的代码实现py-faster-rcnn,用的框架是caffe,由于对caffe不熟悉,所以在github上找了一个tensorflow版本的代码实现,地址是tf-faster-rcnn
在github上阅读代码之前,肯定是要先读一遍readme,根据作者写的说明将代码运行起来,这样也便于后面在代码中添加log来分析代码。
1.安装环境
下载代码
git clone https://github.com/endernewton/tf-faster-rcnn.git
保证除了tensorflow外还需要cython
, opencv-python
, easydict这三个包。
sudo pip install Cython
sudo pip install opencv-python
sudo pip install easydict
根据自己的电脑配置来修改setup.py
cd tf-faster-rcnn/lib
vim setup.py
比如根据我的电脑是GTX 1080 (Ti),所以修改了-arch为sm_61,具体的型号可以在README中查看。
extra_compile_args={'gcc': ["-Wno-unused-function"],
'nvcc': ['-arch=sm_61',
'--ptxas-options=-v',
'-c',
'--compiler-options',
"'-fPIC'"]},
include_dirs = [numpy_include, CUDA['include']]
如果我们的训练电脑只有CPU,那么可以把./lib/model/config.py中的__C.USE_GPU_NMS = True改为False。
然后运行make编译出gpu_nms.so和cpu_nms.so,这部分是原作者为nms做GPU加速而设计出来的代码。
2.准备数据
下载VOCdevkit
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCdevkit_08-Jun-2007.tar
tar xvf VOCtrainval_06-Nov-2007.tar
tar xvf VOCtest_06-Nov-2007.tar
tar xvf VOCdevkit_08-Jun-2007.tar
创建软链接
cd $FRCN_ROOT/data
ln -s $VOCdevkit VOCdevkit2007
3.下载Pre-trained Weights
./data/scripts/fetch_faster_rcnn_models.sh
下载使用Resnet101网络对VOC07+12数据集训练出来的weights。如果无法下载可以试试作者提供的google drive下载。
下载的文件解压后放在data目录下,然后创建软链接
NET=res101
TRAIN_IMDB=voc_2007_trainval+voc_2012_trainval
mkdir -p output/${NET}/${TRAIN_IMDB}
cd output/${NET}/${TRAIN_IMDB}
ln -s ../../../data/voc_2007_trainval+voc_2012_trainval ./default
cd ../../..
我们准备的数据是VOC2007,而下载的weights是根据2007和2012进行训练的,不过我们只是需要将流程跑通,不下载VOC2012关系不大。
4.运行demo和test
运行demo
GPU_ID=0
CUDA_VISIBLE_DEVICES=${GPU_ID} ./tools/demo.py
可以看到对data/demo中的图片都进行了预测。
运行test
GPU_ID=0
./experiments/scripts/test_faster_rcnn.sh $GPU_ID pascal_voc_0712 res101
可以得到对每个类别预测的准确率
Saving cached annotations to /local/share/DeepLearning/stesha/tf-faster-rcnn-master/data/VOCdevkit2007/VOC2007/ImageSets/Main/test.txt_annots.pkl
AP for aeroplane = 0.8300
AP for bicycle = 0.8684
AP for bird = 0.8129
AP for boat = 0.7411
AP for bottle = 0.6853
AP for bus = 0.8764
AP for car = 0.8805
AP for cat = 0.8830
AP for chair = 0.6231
AP for cow = 0.8683
AP for diningtable = 0.7080
AP for dog = 0.8852
AP for horse = 0.8727
AP for motorbike = 0.8297
AP for person = 0.8272
AP for pottedplant = 0.5319
AP for sheep = 0.8115
AP for sofa = 0.7767
AP for train = 0.8461
AP for tvmonitor = 0.7938
Mean AP = 0.7976
~~~~~~~~
Results:
0.830
0.868
0.813
0.741
0.685
0.876
0.880
0.883
0.623
0.868
0.708
0.885
0.873
0.830
0.827
0.532
0.811
0.777
0.846
0.794
0.798
~~~~~~~~
5.训练数据集
基于ImageNet的分类训练的权重来训练Faster RCNN,所以我们需要先下载ImageNet训练权重
mkdir -p data/imagenet_weights
cd data/imagenet_weights
wget -v http://download.tensorflow.org/models/vgg_16_2016_08_28.tar.gz
tar -xzvf vgg_16_2016_08_28.tar.gz
mv vgg_16.ckpt vgg16.ckpt
cd ../..
然后就可以训练了,也可以将数据集替换成自己的数据进行训练。
./experiments/scripts/train_faster_rcnn.sh 0 pascal_voc vgg16
代码分析
模型训练
1.配置和数据准备
当我们运行train_faster_rcnn.sh进行训练时实际上是运行python ./tools/trainval_net.py并且传入了一些参数。在trainval_net.py一开始会打印出所有参数
if __name__ == '__main__':
args = parse_args()
print('Called with args:')
print(args)
output:
Called with args:
Namespace(cfg_file='experiments/cfgs/vgg16.yml', imdb_name='voc_2007_trainval', imdbval_name='voc_2007_test', max_iters=70000, net='vgg16', set_cfgs=['ANCHOR_SCALES', '[8,16,32]', 'ANCHOR_RATIOS', '[0.5,1,2]', 'TRAIN.STEPSIZE', '[50000]'], tag=None, weight='data/imagenet_weights/vgg16.ckpt')
然后读取cfg_file中的配置信息放入config.py,整理set_cfgs中的信息后也放入config.py。常用的配置信息一开始已经放入config.py中了,这步操作相当于是增加了一些网络特有的配置信息。代码如下
if args.cfg_file is not None:
cfg_from_file(args.cfg_file)
if args.set_cfgs is not None:
cfg_from_list(args.set_cfgs)
接着准备imdb和roidb
imdb, roidb = combined_roidb(args.imdb_name)
print('{:d} roidb entries'.format(len(roidb)))
imdb是imdb.py的类对象,便于后面使用imdb提供的方法。
roidb是通过_load_pascal_annotation解析xml文件,获取其中ground truth的boxes,gt_classes,gt_overlaps,flipped,seg_areas信息。
boxes的shape是(len(objs), 4),表示图片中每个元素有一组box信息:xmin,xmax,ymin,ymax
gt_classes的shape是len(objs),图片中每个元素有一个数字表示的类别信息cls
gt_overlaps的shape是(len(objs), num_classes),图片中每个类别有一个对应cls位置为1.0,其他位置都为0的矩阵。
flipped表示是原图还是翻转图True或者False。
seg_areas的shape是len(objs),每个类别有一个矩阵面积。
然后在prepare_roidb函数的调用过程中还会增加一些信息到roidb中:
image表示对应的image的路径
width表示图片的宽
height表示图片的长
max_overlaps表示gt_overlaps每一行最大的值。因为是ground truth的最大值,所以都是1.0,比如一张图片