首先非常感谢github以及诸多博客,感受到论坛的知识贡献的强大,让我有充分的理由不断去学习深度学习的知识,让自己有信心坚持下去,参考了诸多博客。由于自己较笨,用了近一个月的时间把faster-rcnn原理以及代码高的清除一点,我会按照自己的摸索过程讲解faster-rcnn。
本文主要应用的是天猫提供天池的数据集,数据集下载位置在https://tianchi.aliyun.com/competition/information.htm?spm=5176.100067.5678.2.37fd6eed6Eacua&raceId=231652,主要目的是识别图像中的不同中文英文等字符
本文的代码在网址:https://github.com/chenmingwei00/tian_Faster-RCNN_TF_1
1/原始论文翻译,(由于自己想从原始出发到代码的详细解析就按照这样顺序)
2/代码的解析,
3/训练VOCdevkit2007数据集
4/组织训练自己的数据集
四/组织训练自己的数据集
通过第三章的训练voc2007数据集,构造自己的训练数据集,需要做的是两个方面:
(1)构造自己的适合模型固定格式训练数据集,我是按照voc2007的训练数据集进行更改;
生成roi感兴趣区域xml文件,文件格式与voc.xml相同,文件格式如下:
VOC2007
000001.jpg
Fried Camels
Jinky the Fruit Bat
353
500
3
0
从xml文件中可以看到,共需要的主要信息包括:
(1__ 文件名称例如:000010.jpg
(2__ size图片的大小,长宽, 从cv2.imread() and shape得到一张图像大小为480,354,3,;
而xml中的文件是354,480,3;再分析一张图像000009.jpg 大小是375,500,3 ,xml中是
500,375,3;可以看出image.shape的第二个维度是xml中第一个;
(3__ 检测物体中的内容:类别,pose摆姿,按照未指定,trauncated 就目前按照未截断0,diffcult
0, bndbox信息,寻找四个坐标的(xmin,xmax,ymin,ymax)
(4__ 然后在pascal_voc.py文件中增加类别,增加的类别分别是:
"ch","en","numb","chara","ch_en","ch_chara","ch_numb",
"en_chara","en_numb","chara_numb","ch_en_chara","ch_en_numb",
"ch_chara_numb","en_chara_numb","chara_ch_numb+en","others"
之所以要分的那么细原始想法是相对不同的数据分别训练不同的字符识别分类器。
然后把生成的.xml文件复制到项目对应的文件夹:
/home/*/tian_Faster-RCNN_TF/data/VOCdevkit2007/VOC2007/Annotations/$.xml,*代表你的计算机对应的项目文件夹
$代表不同数字图像的下标
然后把对应标签的原始图像复制到项目对应的文件夹下:
/home/*/tian_Faster-RCNN_TF/data/VOCdevkit2007/VOC2007/JPEGImages/$.jpg
在看完twnsorflow-faster-rcnn代码之后,主要用到的是
/home/*/fast_cnn/tian_Faster-RCNN_TF/data/VOCdevkit2007/VOC2007/ImageSets/Main/trainval.txt 这个文件夹下的内容,这个文件内容就是xml以及原始图像对应的$数字下标信息,可以说是哪些数据参加了训练。
(2)更改对应的代码位置,生成适合自己训练数据集的模式;
需要更改的主要是四个位置,就可以训练自己的数据集:
1/更改整个图模型文件中类别属性,所在位置在
/home/*/tian_Faster-RCNN_TF/lib/networks/VGGnet_train.py中的
n_classes = 21更改为n_classes=17#自己自定义的类别个数
2/更改文件/home/*/tian_Faster-RCNN_TF/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')
更改成自己的类别字符数,留下__background__', # always index 0,也有自己对应的背景。
3/更改文件/home/*/tian_Faster-RCNN_TF/lib/datasets/pascal_voc.py中
def _load_pascal_annotation(self, index):中的
for ix, obj in enumerate(objs): bbox = obj.find('bndbox')#对应xml中的属性label # Make pixel indexes 0-based 基于0的像素坐标,应该是矩形左下角以及右上角的坐标 x1 = float(bbox.find('xmin').text) - 1 y1 = float(bbox.find('ymin').text) - 1 x2 = float(bbox.find('xmax').text) - 1 y2 = float(bbox.find('ymax').text) - 1
这一点比较重要,由于voc2007对应的label的xmin,ymin,xmax,ymax对应的坐标需要-1,但是对于自己从天猫数据集提供的是共x1,y1,x2,y2,x3,y3,x4,y4四个顶点坐标位置,所以是实际的坐标位置,寻找到[xmin,ymin,xamx,ymax]四个坐标对应的实际位置信息,是不需要再-1的操作,由于有的坐标xmin或者ymin为0,-1导致,位置偏到到最大值6335,从而使得xmin>xmax,或者ymin>ymax,所以一定要检查这个位置是否需要减1,否则或导致:
loss_bbox = nan,的错误,这是为什么困扰我一个月的重要信息,博客https://blog.csdn.net/hongxingabc/article/details/79048531讲解的非常好,但是具体情况还的需要自己去检查,博客7说在lib/fast_rcnn/bbox_transform.py文件时RuntimeWarning: invalid value encountered in log targets_dw = np.log(gt_widths / ex_widths),然后loss_bbox = nan,
网上很多人说要降低学习率,其实这是指标不治本,不过是把报错的时间推迟罢了,而且学习率过低,本身就有很大的风险陷入局部最优。我非常赞同这个观点,由于模型整体在减少损失,如果减少损失,仍然出现这样的问题,说明所给标记错误,但是仔细取向不一定是标记错误,又或者是代码本身与自己标记的不适合,所以重点刚开始有点误导我,
博客说发现这个问题还是自己的数据集标注越界的问题!!!越界有6种形式:x1<0; x2>width; x2
于是我自己通过自己写的代码,抽样,标记绿色框发现,标注并没有错误,实在是导致我又把文章从头看起,又把代码仔细阅读,以为是数据集某个位置,代码作者的设置值与标注天猫数据集不符导致的结果,不过感谢错误使我认真阅读了文章以及代码等详细注释。
最重要的是怎么去判断这个错误,首先找到错误的位置lib/fast_rcnn/bbox_transform.py
targets_dw = np.log(gt_widths / ex_widths)
而且断言gt_widths>0为错误,所以应该是实际标记有问题导致的,追回
gt_widths=gt_rois[:, 2] - gt_rois[:, 0] + 1.0
而gt_rois是由/lib/rpn_msr/anchor_target_layer_tf.py中的
_compute_targets(ex_rois, gt_rois):调用,这个函数又是由anchor_target_layer_tf.py文件中156行代码
bbox_targets = _compute_targets(anchors, gt_boxes[argmax_overlaps, :])调用,所以gt_rois是由gt_boxes得到,这个gt_boxes可以知道是由lib/datasets/pascal_voc.py中的代码215得到,其中就有每个坐标-1的操作,但是我们标记的坐标由0这个坐标,所以如果仍然使用之前代码会使得xmin或者ymin溢出,数值变的很大,为什么会溢出,仔细分析