faster rcnn 源碼學習-------數據讀入及RoIDataLayer相關模塊解讀


下面我和大家一起從訓練最開始學習作者如何將原始數據讀入並通過RoIDataLayer轉化成網絡訓練所需的數據的總體過程。

訓練從./tools/train_net.py開始,進入主函數,我們只關注跟數據有關的模塊。

首先是imdb, roidb = combined_roidb(args.imdb_name)語句,傳入的參數imdb_name默認是“voc_2007_trainval”,這只是一個數據集的名字而已,進入該文件下的combined_roidb函數,該函數首先有個內部函數get_roidb,下面有調用,進入這函數第一行imdb = get_imdb(imdb_name),這個get_imdb為factory中的函數,細看可以知道get_imdb這個函數通過給數據集的名字返回了該數據集對應的類的對象。

到現在我們可以通過一些變量名知道imdb即影像數據集,roidb即感興趣區域的數據集,factory即為工廠,它的函數get_imdb根據名字返回數據集對應的類的對象。假如imdb_name為“voc_2007_trainval”,我們可以知道get_imdb返回的是pascal_voc(‘trainval’, ‘2007’),而進入pascal_voc文件,我們可以看到他是一個繼承於imdb類的子類(class pascal_voc(imdb):),在init函數中,我們可以知道該類記錄了文件路徑目標類別還有影像擴展名等與數據集相關的內容,而父類imdb中則是名字等一般性的內容。

了解了這些內容以后,我們回到combined_roidb函數的get_roidb函數繼續往下讀,通過get_imdb記錄了數據集的路徑之類的信息后。get_roidb函數又調用了語句imdb.set_proposal_method(cfg.TRAIN.PROPOSAL_METHOD),在config.py中我們看到cfg.TRAIN.PROPOSAL_METHOD值是selective_search,但在/experiments/cfgs/faster_rcnn_end2end.yml中它的值是gt,而imdb的set_proposal_method函數里為method = eval('self.' + method + '_roidb')    self.roidb_handler = method其中eval函數把字符串當成表達式求值,從而我們知道下一行調用了gt_roidb函數,進入pascal_voc下的gt_roidb函數,其中關於cache相當於緩存加速未來調用的,可以不管。我們看到該函數核心語句gt_roidb = [self._load_pascal_annotation(index)  for index in self.image_index]在數據集類pascal_voc中我們知道image_index記錄的是所有影像名的列表,可以知道對每張影像名調用_load_pascal_annotation,進入該函數一眼可以看到在路徑后面加了“Annotations”即可以知道該函數讀取的是影像對應存儲目標的xml文件。最后返回了“boxes”,“gt_classes”等構成的字典。

隨后get_roidb函數調用了get_training_roidb(imdb),進入fast_rcnn下的train.py文件,進入get_training_roidb函數,調用的append_flipped_images函數通過名字可以看出是增加翻轉的,可以不管,然后該函數又調用了prepare_roidb,從上面我們已經知道image_index記錄的是所有影像名的列表,在roidb.py中prepare_roidb通過循環for i in xrange(len(imdb.image_index))對每張影像在上面gt_roidb函數讀取到的內容“gt_overlaps”進行了求最大處理,並記錄影像路徑還有影像高寬等信息在roidb中並返回,返回的roidb是一個長度與影像數一致的列表。由此知該函數即如函數名所示做准備prepare。

現在回到combined_roidb函數,語句roidbs = [get_roidb(s) for s in imdb_names.split('+')]我們可以知道對於每個數據集返回了帶有該數據集信息的imdb和包含每張影像感興趣區域信息的roidb(包括每張影像點目標和影像寬高等信息),事實上roidb屬於imdb。

繼續往下看,train_net.py調用了train_net(args.solver, roidb, output_dir,pretrained_model=args.pretrained_model,max_iters=args.max_iters)函數,此函數為fast_rcnn/train.py中的train_net函數該函數首先調用了filter_roidb,如函數名即對roi進行過濾,然后調用了SolverWrapper,即是solver的封裝類的對象,在init函數中,開始都是導入網絡之類的准備性工作,在最后一句話中,調用了self.solver.net.layers[0].set_roidb(roidb),這句話很關鍵,即調用了網絡第一層也即是prototxt文件的第一層即RoIDataLayer層的set_roidb函數,把之前讀取的roidb對象傳進了網絡。

到現在我們再來看roidb對象里到底記錄了哪些內容呢?包括數據集所有影像的影像路徑,所有影像對應的目標,以及寬高等信息。有了這些信息,就可以在RoIDataLayer層的前向傳播函數調用get_next_minibatch,該函數首先調用了_get_next_minibatch_inds此批次運行的影像下標,然后獲取他們對應的roidb對象后組成列表,傳進get_minibatch函數。在RoIDataLayer層中輸出為data,im_info和gt_boxes,在get_minibatch函數中,他把所有的輸出信息弄成blob以便進行前向傳播。data通過roidb的“image”記錄的路徑信息然后調用opencv的讀影像函數進行讀取並進行尺度縮放后輸出,對應代碼為im_blob, im_scales = _get_image_blob(roidb, random_scale_inds)   blobs = {'data': im_blob},而其余的gt_boxes信息之前已經保存,可以直接將之前的信息保存到對應的blob結構中,最后輸出。blobs['gt_boxes'] = gt_boxes   blobs['im_info'] = np.array(  [[im_blob.shape[2], im_blob.shape[3], im_scales[0]]], dtype=np.float32),最后返回blob,在前向傳播中輸出top layer。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM