关键词:
【说明】:欢迎加入:faster-rcnn 交流群 238138700,关于imdb和roidb的生成都是在函数train_rpn的中,所以我们从这个函数开始,逐个跟进看如何执行得到我们需要的imdb和roidb:
def train_rpn(queue=None, imdb_name=None, init_model=None, solver=None,
max_iters=None, cfg=None):
"""Train a Region Proposal Network in a separate training process.
"""
# Not using any proposals, just ground-truth boxes
cfg.TRAIN.HAS_RPN = True
cfg.TRAIN.BBOX_REG = False # applies only to Fast R-CNN bbox regression
cfg.TRAIN.PROPOSAL_METHOD = 'gt'
cfg.TRAIN.IMS_PER_BATCH = 1
print 'Init model: '.format(init_model)
print('Using config:')
pprint.pprint(cfg)
import caffe
_init_caffe(cfg)
roidb, imdb = get_roidb(imdb_name) # 调用函数,返回训练数据
print 'roidb len: '.format(len(roidb))
output_dir = get_output_dir(imdb)
print 'Output will be saved to `:s`'.format(output_dir)
model_paths = train_net(solver, roidb, output_dir, #传入数据roidb,供训练
pretrained_model=init_model,
max_iters=max_iters)
# Cleanup all but the final model
for i in model_paths[:-1]:
os.remove(i)
rpn_model_path = model_paths[-1]
# Send final model path through the multiprocessing queue
queue.put('model_path': rpn_model_path)
所以,进入get_roidb函数:
def get_roidb(imdb_name, rpn_file=None):
imdb = get_imdb(imdb_name) # 调用该函数,返回imdb
print 'Loaded dataset `:s` for training'.format(imdb.name)
imdb.set_proposal_method(cfg.TRAIN.PROPOSAL_METHOD)
print 'Set proposal method: :s'.format(cfg.TRAIN.PROPOSAL_METHOD)
if rpn_file is not None:
imdb.config['rpn_file'] = rpn_file
roidb = get_training_roidb(imdb) #利用imdb,产生roi_db
return roidb, imdb
所以我们要先看imdb是如何产生的,然后看如何借助imdb产生roidb
def get_imdb(name):
"""Get an imdb (image database) by name."""
if not __sets.has_key(name):
raise KeyError('Unknown dataset: '.format(name))
return __sets[name]()
从上面可见,get_imdb这个函数的实现原理:_sets是一个字典,字典的key是数据集的名称,字典的value是一个lambda表达式(即一个函数指针),
__sets[name]()
这句话实际上是调用函数,返回数据集imdb,下面看这个函数:
for year in ['2007', '2012']:
for split in ['train', 'val', 'trainval', 'test']:
name = 'voc__'.format(year, split)
__sets[name] = (lambda split=split, year=year: pascal_voc(split, year))
所以可以看到,执行的实际上是pascal_voc函数,参数是split 和 year(ps:在train_vpn函数中,name是voc_2007_trainval,所以这里对应的split和year分别是trainval和2007);
很明显,pascal_voc是一个类,这是调用了该类的构造函数,返回的也是该类的一个实例,所以这下我们清楚了imdb实际上就是pascal_voc的一个实例;
那么我们来看这个类的构造函数是如何的,以及输入的图片数据在里面是如何组织的:
该类的构造函数如下:基本上就是设置了imdb的一些属性,比如图片的路径,图片名称的索引,并没有把真实的图片数据放进来
class pascal_voc(imdb):
def __init__(self, image_set, year, devkit_path=None):
imdb.__init__(self, 'voc_' + year + '_' + image_set)
self._year = year # 设置年,2007
self._image_set = image_set # trainval
self._devkit_path = self._get_default_path() if devkit_path is None \\
else devkit_path # 数据集的路径'/home/sloan/py-faster-rcnn-master/data/VOCdevkit2007'
self._data_path = os.path.join(self._devkit_path, 'VOC' + self._year) # '/home/sloan/py-faster-rcnn-master/data/VOCdevkit2007/VOC2007'
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') # 21个类别
self._class_to_ind = dict(zip(self.classes, xrange(self.num_classes))) #给每个类别赋予一个对应的整数
self._image_ext = '.jpg' # 图片的扩展名
self._image_index = self._load_image_set_index() # 把所有图片的名称加载,放在list中,便于索引读取图片
# Default to roidb handler
self._roidb_handler = self.selective_search_roidb
self._salt = str(uuid.uuid4())
self._comp_id = 'comp4'
# PASCAL specific config options
self.config = 'cleanup' : True,
'use_salt' : True,
'use_diff' : False,
'matlab_eval' : False,
'rpn_file' : None,
'min_size' : 2
# 这两句就是检查前面的路径是否存在合法了,否则后面无法运行
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)
那么有了imdb之后,roidb又有什么不同呢?为什么实际输入train_rpn的数据是roidb呢?
前面我们已经得到了imdb,但是imdb的成员roidb还是空白,啥都没有,那么roidb是如何生成的,其中又包含了哪些信息呢?
imdb.set_proposal_method(cfg.TRAIN.PROPOSAL_METHOD)
上面调用的函数,为imdb添加了roidb的数据,我们看看如何添加的,见下面这个函数:
def set_proposal_method(self, method):
method = eval('self.' + method + '_roidb')
self.roidb_handler = method
这里method传入的是一个str:gt,所以method=eval('self.gt_roidb')
那么关键就是eval函数做了什么操作???分析这个函数分析roidb中每个元素的具体hany
有了roidb后,后面的get_training_roidb(imdb)完成什么功能:将roidb中的元素由5011个,通过水平对称变成10022个;将index这个list的元素相应的也翻一番;
我们看看这个函数:
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">函数如下:这个函数首先对imdb中涉及到的图像做了一个水平镜像,使得trainval中的5011张图片,变成了10022张图片;然后调用函数prepare_roidb函数准备数据(ps:我觉得作者这些函数的层层嵌套,又没做多大事情,实在是让结构不那么美观)</span>
def get_training_roidb(imdb):
"""Returns a roidb (Region of Interest database) for use in training."""
if cfg.TRAIN.USE_FLIPPED:
print 'Appending horizontally-flipped training examples...'
imdb.append_flipped_images()
print 'done'
print 'Preparing training data...'
rdl_roidb.prepare_roidb(imdb)
print 'done'
首先我们看看append_flipped_images函数:可以发现,roidb是imdb的一个成员变量,roidb是一个list(每个元素对应一张图片),list中的元素是一个字典,字典中存放了5个key,分别是boxes信息,每个box的class信息,是否是flipped的标志位,重叠信息gt_overlaps,以及seg_areas;分析该函数可知,将box的值按照水平对称,原先roidb中只有5011个元素,经过水平对称后通过append增加到5011*2=10022个;
def append_flipped_images(self):
num_images = self.num_images
widths = self._get_widths()
for i in xrange(num_images):
boxes = self.roidb[i]['boxes'].copy()
oldx1 = boxes[:, 0].copy()
oldx2 = boxes[:, 2].copy()
boxes[:, 0] = widths[i] - oldx2 - 1
boxes[:, 2] = widths[i] - oldx1 - 1 # 新框的xmin和xmax都要更新
assert (boxes[:, 2] >= boxes[:, 0]).all()
entry = 'boxes' : boxes,
'gt_overlaps' : self.roidb[i]['gt_overlaps'],
'gt_classes' : self.roidb[i]['gt_classes'],
'flipped' : True
self.roidb.append(entry) # 把这个新的框添加到roidb中
self._image_index = self._image_index * 2 #将索引的list 复制拼接
然后就是prepare_roidb函数:
def prepare_roidb(imdb):
"""Enrich the imdb's roidb by adding some derived quantities that
are useful for training. This function precomputes the maximum
overlap, taken over ground-truth boxes, between each ROI and
each ground-truth box. The class with maximum overlap is also
recorded.
"""
sizes = [PIL.Image.open(imdb.image_path_at(i)).size
for i in xrange(imdb.num_images)]
roidb = imdb.roidb
for i in xrange(len(imdb.image_index)):
roidb[i]['image'] = imdb.image_path_at(i)
roidb[i]['width'] = sizes[i][0]
roidb[i]['height'] = sizes[i][1]
# need gt_overlaps as a dense array for argmax
gt_overlaps = roidb[i]['gt_overlaps'].toarray()
# max overlap with gt over classes (columns)
max_overlaps = gt_overlaps.max(axis=1)
# gt class that had the max overlap
max_classes = gt_overlaps.argmax(axis=1)
roidb[i]['max_classes'] = max_classes
roidb[i]['max_overlaps'] = max_overlaps
# sanity checks
# max overlap of 0 => class should be zero (background)
zero_inds = np.where(max_overlaps == 0)[0]
assert all(max_classes[zero_inds] == 0)
# max overlap > 0 => class should not be zero (must be a fg class)
nonzero_inds = np.where(max_overlaps > 0)[0]
assert all(max_classes[nonzero_inds] != 0)
============================================================================================================================
写到这里,我就想吐槽了,以为数据准备好了么,no,上面只是准备好了roidb的相关信息而已;
我表示这个作者搞的太麻烦了,结构不够扁平化,简单的事情用多个函数绕来绕去,受不了了;
真正的数据处理操作是在
class RoIDataLayer(caffe.Layer): 类的
def forward(self, bottom, top):函数中开始的,这个类在faster-rcnn-root/lib/roi_data_layer/layer.py文件中
blobs = self._get_next_minibatch()这句话产生了我们需要的数据blobs;这个函数又调用了minibatch.py文件中的def get_minibatch(roidb, num_classes):函数;
然后又调用了def _get_image_blob(roidb, scale_inds):函数;在这个函数中,我们终于发现了cv2.imread函数,也就是最终的读取图片到内存的地方:
def _get_image_blob(roidb, scale_inds):
"""Builds an input blob from the images in the roidb at the specified
scales.
"""
num_images = len(roidb)
processed_ims = []
im_scales = []
for i in xrange(num_images):
im = cv2.imread(roidb[i]['image']) #终于在这里读取图片了
if roidb[i]['flipped']:
im = im[:, ::-1, :]
target_size = cfg.TRAIN.SCALES[scale_inds[i]]
im, im_scale = prep_im_for_blob(im, cfg.PIXEL_MEANS, target_size,
cfg.TRAIN.MAX_SIZE)
im_scales.append(im_scale)
processed_ims.append(im)
# Create a blob to hold the input images
blob = im_list_to_blob(processed_ims)
return blob, im_scales
作者:香蕉麦乐迪-sloanqin-覃元元
如何在faster-rcnn上训练自己的数据集
参考技术A不要发私信 查看详情
faster-rcnn训练自己的数据集——备忘
...。刚刚调通,记下来,以备以后自己少走些弯路。配置py-faster-rcnn没什么好记的,文档也很多。先说下数据集,需要准备三个文件夹:Annotations Images &n 查看详情
深度学习caffe实战笔记(19)windows平台faster-rcnn制作自己的数据集
...过程,这篇博客先介绍如果制作voc2007自己的数据集用于faster-rcnn训练,下一篇博客介绍如何用faster-rcnn训练自己的数据。1、准备图像图像要用.jpg或者jpeg格式的,如果是png或者其它格式,自己转换一下就好,图像名称要用000001.jpg... 查看详情
faster-rcnn训练自己的数据集
...n.net/sinat_30071459/article/details/50723212按照下面这个博客修改faster-rcnn源码,训练自己的数据:http://blog.csdn.net/sinat_30071459/article/details/51332084训练自己的数据的时候如果提示assert(boxes[:,2] 查看详情
转载faster-rcnn+zf用自己的数据集训练模型(matlab版本)
...以看http://blog.csdn.net/sinat_30071459/article/details/50723212) Faster-RCNN源码下载地址:Matlab版本:https://github.com/ShaoqingRen/faster_rcnnPyt 查看详情
faster-rcnn之训练脚本解析:./tools/train_faster_rcnn_alt_opt.py(代码片段)
【说明】:欢迎加入:faster-rcnn交流群238138700,本文分析faster-rcnn训练的python脚本;【debug】:我是把__main__修改了下,放在一个自己定义的函数里面,然后调用debug一步步看执行效果的,读者不妨也... 查看详情
折腾faster-rcnn(三)--训练篇
...(空格分隔):Linux深度学习前面,我们已经成功跑起来faster-rcnn,并且自己动手训练了PascalVOC2007图像集,但是笔者接下来继续沿着官方文件跑PascalVOC2012,训练到第二阶段的某个点,程序就开始报错退出。查看logs发现,找不到... 查看详情
深度学习和目标检测系列教程11-300:小麦数据集训练faster-rcnn模型(代码片段)
@Author:Runsen上次训练的Faster-RCNN的数据格式是xml和jpg图片提供,在很多Object-Detection中,数据有的是csv格式,数据集来源:https://www.kaggle.com/c/global-wheat-detectionwidth和heigth是图片的长和宽,b 查看详情
如何在 mllib 中准备训练数据
】如何在mllib中准备训练数据【英文标题】:Howtopreparefortrainingdatainmllib【发布时间】:2015-12-1619:32:42【问题描述】:TL;DR;如何使用mllib训练我的wiki数据(文本和类别)以预测推文?我无法弄清楚如何转换我的标记化wiki数据,以... 查看详情
深度学习 - 如何为大型分类集准备训练数据?
】深度学习-如何为大型分类集准备训练数据?【英文标题】:DeepLearning-Howtopreparethetrainingdataforlargeclassificationset?【发布时间】:2018-03-2519:45:09【问题描述】:所以我有大量的课程(现在说500个,随着时间的推移可能会增加)。... 查看详情
windows下使用自己制作的数据集训练faster-rcnn(tensorflow版)用于目标检测
步骤一下载配置windows下tensorflow版faster-rcnn,参考博客:windows10下运行tensorflow版的faster-Rcnn步骤二制作自己的数据集参考博客:http://blog.csdn.net/u011574296/article/details/78953681步骤三用你的Annotations,Imag 查看详情
深度学习和目标检测系列教程10-300:通过torch训练第一个faster-rcnn模型(代码片段)
@Author:Runsen上次介绍了Faster-RCNN模型,那么今天就开始训练第一个Faster-RCNN模型。本文将展示如何在水果图像数据集上使用Faster-RCNN模型。代码的灵感来自此处的Pytorch文档教程和Kagglehttps://pytorch.org/tutorials/intermediate/torc... 查看详情
为啥faster-rcnn端到端训练只做近似?
】为啥faster-rcnn端到端训练只做近似?【英文标题】:Whyfaster-rcnnendtoendtrainingonlymakesapproximation?为什么faster-rcnn端到端训练只做近似?【发布时间】:2018-05-0107:07:05【问题描述】:在更快的rcnn(https://arxiv.org/abs/1506.01497)中,有两种... 查看详情
ai系统架构之算法平台设计
...且管理数据在离线、近线和在线模式之间的分布。*模型训练和评估主要是使用各种基础平台(Spark/Tensorflow/Xgboost等)训练模型,从数据中获取可以应用的模型和规则。训练出来的模型,需要进行验证和评估,评估包括在训练集、... 查看详情
在自定义数据集上训练 Faster-RCNN 模型时加载检查点
】在自定义数据集上训练Faster-RCNN模型时加载检查点【英文标题】:LoadingcheckpointswhiletrainingaFaster-RCNNmodelonacustomdataset【发布时间】:2021-12-1002:16:09【问题描述】:我正在尝试使用Faster-RCNN架构(准确地说是FasterR-CNNResNet50V1640x640,... 查看详情
训练数据准备
】训练数据准备【英文标题】:DataPreparationfortraining【发布时间】:2018-03-2908:47:52【问题描述】:我正在尝试通过创建字符文本的一种热编码来准备数据文件,之后我可以使用它来训练我的模型进行分类。我有一个由字符行组成... 查看详情
pytorch Faster-RCNN 的验证损失
】pytorchFaster-RCNN的验证损失【英文标题】:ValidationlossforpytorchFaster-RCNN【发布时间】:2020-06-0522:10:21【问题描述】:我目前正在使用从pytorch预训练的Faster-RCNN模型(例如在torchvisiontutorial中)的迁移学习对自定义数据集进行对象检... 查看详情
faster-rcnn之shell脚本开始训练:./experiments/scripts/faster_rcnn_alt_opt.sh0zfpascal_voc(代码片段)
【说明】:欢迎加入:faster-rcnn交流群238138700,这是作者提供的一个运行训练的脚本,我们来看看这个脚本做了什么工作,如果要运行需要输入哪些参数;【使用】:如果要训练一个网络,可以在she... 查看详情