? ? ? ? ? ? 如下列舉了 將數據集做成VOC2007格式用于Faster-RCNN訓練的相關鏈接。
- RCNN系列實驗的PASCAL VOC數據集格式設置?
- 制作VOC2007數據集用于Faster-RCNN訓練
- 將數據集做成VOC2007格式用于Faster-RCNN訓練
這一篇比較詳細地介紹了如何制造voc2007的所有文件,內含相關軟件和代碼,值得一看。 - voc2007數據集的下載和解壓
下面的部分介紹了py-faster-rcnn源碼中關于產生imdb與roidb的方法。
- ? ??faster-rcnn 之訓練數據是如何準備的:imdb和roidb的產生
- faster rcnn源碼解讀(四)之數據類型imdb.py和pascal_voc.py(主要是imdb和roidb數據類型的解說)
- py-faster-rcnn源碼解讀系列(二)——pascal_voc.py
這里簡單說一下Imdb與roidb。
imdb是作者封裝的一個圖片數據庫類,內含數據庫的名字,比如默認的是voc_2007_trainval ,部分定義如下:
class imdb(object):"""Image database."""def __init__(self, name):self._name = nameself._num_classes = 0self._classes = []self._image_index = []self._obj_proposer = 'selective_search'self._roidb = Noneself._roidb_handler = self.default_roidb #(handle本來是指針,這里就當做引用)# Use this dict for storing dataset specific config optionsself.config = {}@propertydef name(self):return self._name@propertydef num_classes(self):return len(self._classes)@propertydef classes(self):return self._classes@propertydef image_index(self):return self._image_index@propertydef roidb_handler(self):return self._roidb_handler@roidb_handler.setterdef roidb_handler(self, val):self._roidb_handler = val
##!!!!!!設置roidbdef set_proposal_method(self, method):method = eval('self.' + method + '_roidb') # python中eval是可以具體運行里面的字符串的,這里指運行:self.gt_roidb,函數在pascal_voc.py中。self.roidb_handler = method@propertydef roidb(self):# A roidb is a list of dictionaries, each with the following keys:# boxes# gt_overlaps# gt_classes# flippedif self._roidb is not None:return self._roidbself._roidb = self.roidb_handler()return self._roidb#cache_path: /data1/caiyong.wang/program/py-faster-rcnn.back_up/data/cache 緩沖路徑@propertydef cache_path(self):cache_path = osp.abspath(osp.join(cfg.DATA_DIR, 'cache'))if not os.path.exists(cache_path):os.makedirs(cache_path)return cache_path@propertydef num_images(self):return len(self.image_index)
其中包含了roidb,roidb翻譯過來就是roi database.其實就是目標檢測包圍盒,從上面也可以看出,
roidb是字典的列表,每項都是一張圖片,如下的每一項都是一張圖片上多個盒子的信息,因此是二維數組:
# A roidb is a list of dictionaries, each with the following keys:
?#??- ?boxes 一個二維數組 ? 每一行存儲 xmin ymin xmax ymax ,行指的多個box的序號
# - ?gt_classes存儲了每個box所對應的類索引(類數組在初始化函數中聲明)
# - ?overlap是一個二維數組,行指box的序號,列共有21列,存儲的是0.0或者1.0 ,當box對應的類別時,自然為1.0.這實際上是指對于ground truth box,由于這里的候選框就是ground truth box,所以自然重疊后為1,而與其他的自然重疊設為0.后來被轉成了稀疏矩陣.
# - ?seg _areas存儲著 box的面積
#- ?flipped 為false 代表該圖片還未被翻轉(后來在train.py里會將翻轉的圖片加進去,用該變量用于區分)
產生imdb與roidb的主要代碼是:
def get_roidb(imdb_name, rpn_file=None):imdb = get_imdb(imdb_name)#通過工廠類獲取數據庫信息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_fileroidb = get_training_roidb(imdb)#獲得訓練數據return roidb, imdb
步驟是
1. 通過 lib/datasets/factory.py獲取pascal_voc對象。
2.?pascal_voc繼承自imdb,進一步定義了該數據庫下的一些函數。
如下是pascal_voc的一些成員舉例:
#下面是成員變量的初始化:
#{
# year:’2007’
# name:'voc_2007_trainval'
# image _set:’trainval’
# devkit _path:’data/VOCdevkit2007’
# data _path:’data /VOCdevkit2007/VOC2007’
# classes:(…)_如果想要訓練自己的數據,需要修改這里_
# class _to _ind:{…} _一個將類名轉換成下標的字典 _
# image _ext:’.jpg’
# image _index: [‘000001’,’000003’,……]_根據trainval.txt獲取到的image索引_
# roidb _handler: <Method gt_roidb >
# salt: <Object uuid >
# comp _id:’comp4’
# config:{…}
#}
3.?通過 lib/datasets/imdb.py 中的set_proposal_method 獲取roidb.
def set_proposal_method(self, method):method = eval('self.' + method + '_roidb') # python中eval是可以具體運行里面的字符串的,這里指運行:self.gt_roidb,函數在pascal_voc.py中。self.roidb_handler = method
這里默認是eval('self.gt_roidb'),self.gt_roidb,函數在pascal_voc.py中。定義了ground truth的box的一些信息。
4. 通過lib/fast rcnn/train.py中的如下函數獲取訓練數據。
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'return imdb.roidb
這里面進行了圖片的翻轉,其實是box的翻轉(見?lib/datasets/imdb.py/append_flipped_images)
以及lib/roi_data_layer/roidb/rdl_roidb對象的prepare_roidb ,這個函數豐富了roi的一些信息,新增了每一個圖片的roidb的圖片路徑,大小,以及每個box對應的最大重疊,和最大重疊對應的label等。
def prepare_roidb(imdb):"""Enrich the imdb's roidb by adding some derived quantities thatare useful for training. This function precomputes the maximumoverlap, taken over ground-truth boxes, between each ROI andeach ground-truth box. The class with maximum overlap is alsorecorded."""sizes = [PIL.Image.open(imdb.image_path_at(i)).sizefor i in xrange(imdb.num_images)]roidb = imdb.roidbfor i in xrange(len(imdb.image_index)): #此時如果在前面調用了imdb.append_flipped_images,則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 argmaxgt_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 overlapmax_classes = gt_overlaps.argmax(axis=1)roidb[i]['max_classes'] = max_classesroidb[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)