基于Tensorflow的Faster R-CNN目标检测算法之训练自己的Dataset及Model

目标检测 专栏收录该内容
2 篇文章 0 订阅

此乃本人的第二篇csdn博客,上一篇介绍了用faster r-cnn在cpu下来运行一个demo,实现图片的目标检测。本博客就是要介绍如何修改faster r-cnn的源码,建立自己的数据集,然后训练模型,借鉴别人的代码为自己所用,进而实现实现自己的项目。

1. 用数据集测试预训练好的模型

我的第一篇博客是采用预训练好的模型来测试图片,这里采用VOC2007测试集来测试预训练好的模型的好坏,用大量的图片来测试模型检测目标的精度,模型还是第一篇博客里面的Resnet101(在ImageNet和VOC0712上训练过的模型)。需要执行test_faster_rcnn.sh脚本,看其代码会发现,其实所用的就是VOC2007的test测试集。

因此这里只需要一个预训练好的模型和VOC2007的test数据集即可。

1.修改源码

把tf-faster-rcnn/lib/datasets/voc_eval.py的第121行的
with open(cachefile,‘w’) as f
改成:
with open(cachefile,‘wb’) as f
同时还要把第105行的

cachefile = os.path.join(cachedir, '%s_annots.pkl' % imagesetfile)

改为

cachefile = os.path.join(cachedir, '%s_annots.pkl' % imagesetfile.split("/")[-1].split(".")[0])

2. 下载VOC2007数据集

下面以voc2007为例
下载训练和验证集:
http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar
下载测试集:
http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar
下载工具包:
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

最后把VOCdevkit文件夹拷贝到tf-fater-rcnn/data路径下,并重命名为VOCdevkit2007

3.执行测试脚本验证模型准确率

执行如下命令:
运行的参数中是GPU运行的参数设置,但是在经过第一篇博客的修改后,gpu_id参数设置为0的话,也是可以运行的。

./experiments/scripts/test_faster_rcnn.sh 0 pascal_voc_0712 res101

如果你成功得到了20类目标的AP的话,那说明你成功啦。如果报错需要看具体是什么错误,下面是我的报错记录。
疑问:只看命令可知就是用VOC0712的test测试集来测试模型的好坏。故:数据集名字是pascal_voc_0712。但是我用的测试集是voc2007啊,为什么是pascal_voc_0712?
在这里插入图片描述
查看上述代码可以发现,是执行第二部分,然后我们这里只用到了测试集,即TEST_IMDB,其实也就是VOC07的test测试集。

4.报错记录

1. 报错:找不到numpy
执行完命令之后,报错如下,numpy是python常用的库,我肯定安装了,查找源码发现脚本是默认用python2来运行的,需要改成python3.
在这里插入图片描述
将两处python改为python3:
在这里插入图片描述
2. 报错:ImportError: No module named ‘yaml’
再次执行命令,报错:ImportError: No module named ‘yaml’,需要安装yaml库:
sudo pip3 install pyyaml(不是pip3 install yaml,我最初就是这样安装的)
3. 报错:数据集不存在test.txt文件。
再次执行命令,报错:不存在test.txt文件,如下:
在这里插入图片描述
VOC2007数据集下载之后,只有这三个txt文件,所以第一种方案:需要把训练集的xml文件重新分配成训练集,测试集,验证集等4个txt文件。第二种方案:把VOC2007的三个文件都下载成功。
在这里插入图片描述
其实是我只下载了第一个和第三个,第二个下载不成功。将两个压缩包解压在一起,所以少了test.txt文件,去下面这个网站下载:
https://pjreddie.com/projects/pascal-voc-dataset-mirror/
4. 报错:default无此文件夹。
再次运行命令,报错:default无此文件夹,如下
在这里插入图片描述
找到此文件夹的母目录,明明存在default啊,但是ls之后,发现没有default,这就奇怪了,需要重新链接一下,然后ls查看是否有default文件夹,如果有就成功了---其实这是错误的,后来才发现,见下面的原因描述就知道了。

在这里插入图片描述
原因:output文件夹要在tf-faster-rcnn-master母目录之下才可以了,上述建立模型软链接的位置错了,所以报错找不到default文件夹。

转自其他博客:执行完demo.py程序后删除tf-faster-rcnn/output/res101/voc_2007_trainval+voc_2012_trainval下的default文件 ,然后再去执行测试文件,因为测试时还要创建一个default文件,那个和现在这个是不一样的,所以如果不删除这个现存的default文件会导致无法测试,显示default文件已存在,创建失败。当然测试完之后如果要运行demo.py文件的话,同样是要删除掉测试时创建的default文件的。(很奇怪,这是我在一个GitHub上的讨论中找到的答案)---但是我好像重新建立了模型的软链接之后就可以运行测试脚本了,by zhguoi。

5.成功运行

成功运行界面如下:
在这里插入图片描述
最终结果如下,给出每个类检测精度的平均值AP。
在这里插入图片描述
—技巧:在CPU下要预测完VOC测试集里面的那么多图片(4952张)还是太慢了,需要n个小时吧。这里我们直接修改test.txt文件,只留前20张图片,看测试效果如何:

在这里插入图片描述
在这里插入图片描述
测试完毕后同样会在output文件夹下建立一个路径为:/output/res101/voc_2007_test/default/res101_faster_rcnn_iter_110000/的文件夹,res101代表网络名称,voc_2007_test代表数据集,与训练不同,该文件夹下不再是模型文件。

总结:用训练好的模型去检测图片和数据集时,关键是要让运行的脚本代码找到模型所在的位置,即:tf-faster-rcnn/output/net名字/数据集名字/default —其下就是四个model文件。net名字和数据集名字在运行./test_faster_rcnn时需要指定,但是运行demo.py时需要在源码中进行修改/指定,默认是res101和pascal_voc_0712,如下所示。only by zhguoi

在这里插入图片描述在这里插入图片描述

2. 用VOC2007训练模型

这里用VOC2007的训练集来训练自己的模型,也就是说不用预训练好的模型了,要训练出自己的模型,但是还是需要预训练好的模型权重文件的。

因此此功能实现是需要:vgg16或res101模型的权重文件和voc2007的训练集就可以了。因为faster-rcnn本身就是用voc2007来训练的实现20类目标检测,所以代码中的类别等参数都不用修改,voc2007训练集也是现成的,所以很简单。

1. 下载模型权重文件并重命名

将其下载并放在data/imagenet_weights文件夹下,重命名,因为后面在调用权重数据的时候名字需要对应的上。
下面将以VGG16模型为例:
$ 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

ResNet101为:
wget -v http://download.tensorflow.org/models/resnet_v1_101_2016_08_28.tar.gz
将resnet_v1_101.ckpt改成res101.ckpt

2. 删除缓存

如果在此之前做过训练的动作,那么需要删除缓存:
#此处注意,如果是使用res101模型训练过,就在output目录下找res101。如果用vgg16模型则在output目录下找vgg16。其它模型类推。
tf-faster-rcnn/output/res101/voc_2007_trainval/default
tf-faster-rcnn/data/cache
tf_faster_rcnn/data/VOCdevkit2007/annotations_cache
若本来就没有训练过则没有生成以上目录,则不用删除。

3.训练和测试

命令如下,训练完就立马测试,两个是一起的,注意这里的数据集是voc2007,所以应该是pascal_voc,不能写成pascal_voc_0712。

./experiments/scripts/train_faster_rcnn.sh [GPU_ID] [DATASET] [NET]
# GPU_ID 是你要使用的GPU编号
# NET  是你采用的网络类型, 可选范围为{vgg16, res50, res101, res152}
# DATASET 是数据集,在train_faster_rcnn.sh中预先定义过{pascal_voc, pascal_voc_0712, coco} ,还可以根据自己需要进行添加
# 所以最终是:
./experiments/scripts/train_faster_rcnn.sh 0 pascal_voc vgg16

训练时界面如下所示,需要迭代70000次,这在CPU下训练要到猴年马月了啊。
在这里插入图片描述
为了走通整个流程,节约训练时间,我使用的是pascal_voc数据集,只需要更改对应数据集的ITERS的就行了:把迭代次数只设置了40次,即在./experiments/scripts/train_faster_rcnn.sh里的第22行把ITERS=70000改成ITERS=20,同时由于train_faster_rcnn.sh中最后有调用test_faster_rcnn.sh,因此记得把./experiments/scripts/test_faster_rcnn.sh的ITERS也改成40,如下所示:
训练界面:这是四个loss
在这里插入图片描述
测试界面:可见测试结果很差,因为只训练了40step,被人都是7万step,没法比。
在这里插入图片描述
最终在下图中目录中生成自己的模型文件(模型结构和权重文件)
在这里插入图片描述

使用以下脚本进行测试:(上面已经测试过了)
./experiments/scripts/test_faster_rcnn.sh 0 pascal_voc vgg16

训练好的模型默认保存在下面的目录:
output/[NET]/[DATASET]/default/

测试输出保存在下面的目录:
output/[NET]/[DATASET]/default/[SNAPSHOT]/

训练和验证的Tensorboard信息保存在以下目录:
tensorboard/[NET]/[DATASET]/default/
tensorboard/[NET]/[DATASET]/default_val/

4. 用此模型对图片进行测试

需要修改demo.py文件里面的代码,默认是res101的。后面详细说如何修改。
修改完成后,运行demo.py,没有报错,成功运行,但是没有跳出检测后的图片很是奇怪。因此把检测后的图片进行保存,来查找原因。
修改demo.py代码如下:
demo(sess,net,im_name)
plt.savefig(’./data/demo-show/’+im_name)
#前面是路径,demo-show文件需要自己创建,也是以项目的根路径进行设置的
#im_name是图片原本的名称,所以在保存的时候,如果还是在测试图片的文件下进行保存,会被覆盖
运行demo.py,结果保存如下,可见都是空白的图,所以没有显示出来。
在这里插入图片描述原因是什么啊?感觉就是训练模型的精度太低了,所以没有检测出来任何东西,只能这样解释了,by zhguoi.
------但是吧,训练自己的模型时,用了预训练好的权重文件了,而且该权重文件也是在voc2007数据集上训练的,只要把权重文件加进来,然后稍微训练几次,精度应该就可以了,反正SSD算法是这样子的,不知道faster rcnn为啥训练结果这么差。

疑问:用官方训练好的模型文件(4个)来做测试,检测效果很好,5张图片保存了5张检测结果,但是为什么一张图片中有好几个目标就检测出一个目标啊,如下图,为什么只有person,没有dog?运行完会弹出12张图片,也就是说一张图片中有多个目标时,它分成了多个图片来显示,每张图片显示单一的目标。这就很奇怪了。
在这里插入图片描述

4. 可视化

训练完成后,可以使用Tensorboard对训练过程的log进行可视化
首先安装tensorboard,不然会报错,不是安装了tensorflow就自动安装了tensorboard的。
$ sudo pip3 install tensorboard
$ tensorboard --helpfull #可查看安装是否成功
然后输入以下命令:
tensorboard --logdir=tensorboard/vgg16/voc_2007_trainval/ --port=7000 &
如下图中res101应该是vgg16,在浏览器中打开http://zhguoi:7000即可。
在这里插入图片描述
在这里插入图片描述

3. 基于faster r-cnn训练自己的数据集

第一次用预训练好的模型去测试几张图片的检测效果(Demo演示);
第二次用VOC2007测试集去验证模型的检测精度(模型测试);
第三次用VOC2007训练集去训练自己的模型,并把上面两个步骤重新走一遍。

接下来就是用自己制作的训练集去修改faster r-cnn的源码来训练出自己的模型了,这跟用voc2007还是不一样的,voc2007是现成的数据集(20类目标),faster r-cnn正好就是用的这些数据集来训练的,所以源码不需要修改。我们这里不仅要自己制作训练集还要修改源码来实现目标检测,让faster r-cnn为自己的项目所用。

因此:这里只需要有自己的数据集和预训练模型权文件就可以了。

1. 制作自己的数据集

需要按照VOC2007格式来制作数据:
VOC2007
├── Annotations #图像标签文件,是.xml格式
├── ImageSets
│ ├── Layout
│ ├── Main #训练和测试用到的数据文件
│ └── Segmentation
└── JPEGImages #图像文件
#Layout和Segmentation文件在这里不需要

1. 推荐采用labelimg工具来进行图像标注,网上自行下载。如何制作见次博客:
https://blog.csdn.net/hitzijiyingcai/article/details/81636455
标注界面如下:
在这里插入图片描述
xml文件格式:

<annotation>
	<folder>fire_data</folder>
	<filename>000001.jpg</filename>    #图像名称
	<path>/home/htu/yc/fire_data/000001.jpg</path>    #路径
	<source>
		<database>Unknown</database>
	</source>
	<size>
		<width>450</width>    #宽
		<height>253</height>    #高
		<depth>3</depth>    #RGB三通道
	</size>
	<segmented>0</segmented>
	<object>
		<name>fire</name>    #目标名称
		<pose>Unspecified</pose>    
		<truncated>0</truncated>
		<difficult>0</difficult>
		<bndbox>    #BBOX值
			<xmin>146</xmin>
			<ymin>22</ymin>
			<xmax>207</xmax>
			<ymax>60</ymax>
		</bndbox>
	</object>
</annotation>

注意:jpg文件名和 xml文件名要对应起来。
其他博客:其中需要说明的是:图像名称一定要命名为000001.jpg,以及xml也要命名为000001.xml格式。我之前用的是1,2,3,4这样命名,结果运行总是会提示Keyerror:“1”。------我的命名方式为:raccoon-1.xml,也可以运行的,之前有人说命名必须是6位数字,这里我验证了不需要那么严格,only by zhguoi。
2. 然后就是划分数据集为训练集,测试集,验证集等,即4个txt文件。

这里我在网上找到了浣熊的数据集,如下:
https://github.com/datitran/raccoon_dataset
我自己其实在网上自己找了208张大熊猫的图片并进行了标志,很快就可以标注完了,我还不知道如何把数据集上传github,这里就拿别人制作好的数据集做演示了,也方便大家同步我的流程。

2. 修改源码

1. 修改类别名称
修改 /tf-faster-rcnn/lib/datasets/pascal_voc.py文件,找到这句话:

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._classes = ('__background__',  # always index 0
                     'raccoon')

2. 修改迭代次数
修改/tf-faster-rcnn/experiments/scripts/train_faster_rcnn.sh文件,找到类似这段代码:

  pascal_voc)
    TRAIN_IMDB="voc_2007_trainval"
    TEST_IMDB="voc_2007_test"
    STEPSIZE="[50000]"
    ITERS=400
    ANCHORS="[8,16,32]"
    RATIOS="[0.5,1,2]"

ITERS后面的数值代表是迭代次数,我改成了400,迭代次数太少精度不高,索性就稍微迭代次数大一点,看最终检测效果如何。由于train_faster_rcnn.sh此文件最后一句话调用了test_faster_rcnn.sh,因此需要将test_faster_rcnn.sh中的代码做相同处理,即改变迭代次数(要与train_faster_rcnn.sh文件中的迭代次数一致)

3. 删除缓存

如果之前做过训练,需要删除之前训练留下的缓存:
1. 删除训练缓存
删除文件夹/tf-faster-rcnn/output/vgg16/voc_2007_trainval/default下所有文件;
删除文件夹/tf-faster-rcnn/data/cache下所有的文件;
2. 删除标记缓存
删除文件夹/VOCdevkit/annotations_cache下的所有文件
注:如果不进行这一步很可能会出现Keyerror:一类的错误日志

4. 训练和测试

执行如下命令:

./experiments/scripts/train_faster_rcnn.sh 0 pascal_voc vgg16

训练过程,希望不会让我失望
在这里插入图片描述
loos意义如下:

‘’‘
# 迭代次数			总损失
iter: 10 / 40000, total loss: 1.274421
	分类损失(有无物体)
>>> rpn_loss_cls: 0.355426
	预测框损失
>>> rpn_loss_box: 0.045310
	分类损失(哪一类)
>>> loss_cls: 0.408049
	预测框损失
>>> loss_box: 0.465636
’‘’

测试界面:意思是8秒检测一张图片吗?这感觉速度也太满了吧,用在无人驾驶中,不早出事了吗?
在这里插入图片描述
60张图片检测完了,报错如下:VOCdevkit2007数据集下面没有results/…/xx.txt文件。
在这里插入图片描述
因为我以为不需要results文件夹呢,我就把results文件夹删除了,从之前完整的VOC2007数据集中拷贝results过来,如下。
在这里插入图片描述再次运行测试命令,检测精度如下:400步才22.3%的精度吗?
在这里插入图片描述
大家看一下这400步的loss走势正常吗?这一直在震荡啊,训练400花了我两个小时,太慢了。
在这里插入图片描述
请教了同事,同事说这loss不收敛啊,是有问题的,要么数据有问题,要么训练次数太少,要么算法代码有问题。我有点不甘心,下了决心训练4000次看看,25s一步,一分钟3步,一小时180步,400需要22小时,其实不止这么多小时,我每天9点开始训练,下午5点多结束训练,晚上不能关机,一关机训练就终止了,只能睡眠,晚上公司电脑要收起来,这样连着训练了三天终于训练完了,都是泪啊,然后怀着激动的心情码字时电脑突然黑屏了,感觉是电脑是累了,还是很伤电脑的。训练结果如下所示:
在这里插入图片描述
测试精度如下:67.6%,这精度也不高啊,干!难道要4万步,还是让我的电脑休息会吧。
在这里插入图片描述
可视化,总loss统计如下,感觉还是震荡啊
在这里插入图片描述

对图片进行测试,干,终于成功啦!精度还可以,就是方框有点大,后面再继续训练的话,我觉得应该就是修正box的准确率了。还是很开心的,以为是代码有问题,晚上加个鸡翅。

在这里插入图片描述
在这里插入图片描述

5. 用训练好的模型测试图片

修改/tf-faster-rcnn/tools/demo.py文件
1. 修改类别CLASSES
将代码:

CLASSES = ('__background__',
           'aeroplane', 'bicycle', 'bird', 'boat',
           'bottle', 'bus', 'car', 'cat', 'chair',
           'cow', 'diningtable', 'dog', 'horse',
           'motorbike', 'person', 'pottedplant',
           'sheep', 'sofa', 'train', 'tvmonitor')

保留’background’这一项,其余改成自己的类,如:

    CLASSES = ('__background__',
               'raccoon')

2. 修改类别数
将代码:

    net.create_architecture("TEST", 21,
                          tag='default', anchor_scales=[8, 16, 32])

将21换成自己的类别数+1,由于我只有一个类“raccoon”,因此这里改成2,如:

        net.create_architecture("TEST", 2,
                              tag='default', anchor_scales=[8, 16, 32])

3. 修改调用模型的名称
找到此代码:

NETS = {'vgg16': ('vgg16_faster_rcnn_iter_70000.ckpt',),'res101': ('res101_faster_rcnn_iter_110000.ckpt',)}

修改调用的模型的名字,我用的是vgg16来训练我的网络,迭代次数设置为400,所以我修改如下:

NETS = {'vgg16': ('vgg16_faster_rcnn_iter_400.ckpt',),'res101': ('res101_faster_rcnn_iter_110000.ckpt',)}

注:这个模型的名字也可以在你存放模型结果的文件夹下查看的,默认存放的位置是:/tf-faster-rcnn/output/vgg16/voc_2007_trainval/default文件夹下的。
4. 修改调用模型的位置
将默认调用的模型网络名称由res101改成vgg16

parser.add_argument('--net', dest='demo_net', help='Network to use [vgg16 res101]',
                        choices=NETS.keys(), default='res101')

改成:

parser.add_argument('--net', dest='demo_net', help='Network to use [vgg16 res101]',
                        choices=NETS.keys(), default='vgg16')

因为我标注的数据集是替换了pascal_voc数据集,因此我的模型是存放在/tf-faster-rcnn/output/vgg16/voc_2007_trainval/default文件夹下的,但是demo.py文件默认的是调用训练pascal_voc_0712数据集的模型,因此我们需要修改调用模型的位置,找到这段代码:

    parser.add_argument('--dataset', dest='dataset', help='Trained dataset [pascal_voc pascal_voc_0712]',
                        choices=DATASETS.keys(), default='pascal_voc_0712')

改为:

    parser.add_argument('--dataset', dest='dataset', help='Trained dataset [pascal_voc pascal_voc_0712]',
                        choices=DATASETS.keys(), default='pascal_voc')

5. 修改测试图片的名字
将待测试图片放在./demo/文件夹下,并在代码中修改图片名字,如下:
在这里插入图片描述
至此,我们已经掌握了如何来运行faster r-cnn工程了,只要你有新的数据集,你就可以用该代码实现任意目标的检测,如果大家有什么疑问可以在下面评论说出问题,我看到了就会解答。如果上述内容有错误地方,也希望大家能够给我评论提出来,谢谢!我会进行修改。

福利:

特此附上我的手稿:

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

疑问:

其实我在想,这不相当于重点就是在如何制作数据集上了吗,大家都知道,制作数据集是一个很繁琐的事情,如何扩大数据集的数量,如何标注的更精确,利用计算能力强的GPU来训练数据集,这些都将提高目标检测的精度,那么检测的精度将与代码无关,大家都是用的这样的代码,只不过是数据集的好坏不同罢了,这还是人工智能吗?我咋感觉有点无脑啊?only by zhguoi

计划:

现在我们会用faster r-cnn的代码了,但是并没有去看代码的具体内容,接下来就是结合faster r-cnn理论知识,去看懂faster r-cnn代码是如何实现目标检测的,一来可以理解faster r-cnn的理论知识,二来可以提高自己的代码能力。
这也是本人的学习思路,如果有幸人可以看到这两篇faster r-cnn的博客,觉得对自己有帮助的话,给点个赞,也相当于给了我支持和力量,后续我会再出一些相关的博客。

祝您学业有成,工作顺利!

洒哥

  • 3
    点赞
  • 0
    评论
  • 7
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页

打赏作者

zhguoi

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值