1. 程式人生 > >Faster rcnn原始碼理解(2)

Faster rcnn原始碼理解(2)

接著上篇的部落格,咱們繼續看一下Faster RCNN的程式碼~

上次大致講完了Faster rcnn在訓練時是如何獲取imdb和roidb檔案的,主要都在train_rpn()的get_roidb()函式中,train_rpn()函式後面的部分基本沒什麼需要講的了,那我們再回到訓練流程中來:

這一步訓練的網路結構見下圖:

訓練的第一步就這麼完成了(RPN網路使用gt_roidb訓練完成),還有,這裡的train_rpn()函式中有涉及到train_net()函式,即用來訓練得到網路模型,我會在訓練fast rcnn時給出講解;之後再進行第二步:

產生proposal的網路結構如下:

這一步是利用上一步訓練好的RPN網路來生成proposals供下一步中的fast rcnn訓練,這裡補充一下,字典mp_kwargs中的引數solver,是使用get_solvers()函式得到的,見下:

由上圖可知,四步訓練時的網路結構都在相應的四個solver檔案有解釋。好了回到訓練流程中,產生proposal的函式是rpn_generate()函式,那我們進入這個函式:

首先設定了什麼預NMS(不太懂),還有就是經過NMS後產生2000個proposals,然後初始化caffe,再用get_imdb()函式得到imdb資料,方法和前面一樣,再用caffe.NET()載入RPN網路,再使用imdb_proposals()得到proposal,那我們就進入這個函式:

該函式的作用就是在所有的圖片上生成proposal,不過作者又嵌套了一個im_proposals()函式,即在一張圖片上產生proposals(這個巢狀看似多餘,但是為後面再添一些測試指令碼提供了方便,我猜rgb大神可能有這個目的),進入im_proposals()函式中:

見上圖,首先用_get_image_blob()函式將圖片資料轉換為caffe的blob格式,進入該函式:

最終得到的blob格式為(batch elem , channel , height , width),im_info格式為[M,N,im_scale],其中im_scale是縮放比例,原始圖片輸入faster rcnn中進行訓練時都需要先縮放成統一的規格;再回到im_proposals()函式中,使用net.forward()函式進行一次前向傳播,獲得proposals,ok。之後再回到imdb_proposals()函式中,最後返回得到的imdb_boxes,即我們從RPN上產生的proposals。再回到rpn_generate()函式中,接著就是將生成的proposals儲存並傳輸到多執行緒中去供下一步訓練使用,這個函式使命就暫時完成了;

再到第三步,訓練fast rcnn網路,見下:

這一步訓練的網路結構如下圖:

注意這時候訓練fast rcnn的roi就是前面訓練好的RPN網路生成的proposals了(訓練RPN網路用的是gt框),相關配置都在mp_kwargs字典中,很明顯,我們要進入train_fast_rcnn()中一探究竟:

這裡首先設定了訓練使用的rpn_roidb方法(RPN用的是gt_roidb方法),由於這時候的cfg.TRAIN.PROPOSAL_METHOD變成了rpn_roidb,所以相應的使用的get_roidb()也相應地改變,此時使用rpn_roidb()方法,進入該函式:

該方法首先先獲得gt_roidb,然後再用_load_rpn_roidb()獲得由RPN產生的roidb,進入該函式:

接著進入create_roidb_from_box_list()函式中:

這個函式凸顯了資料結構的重要性,我們需要重點關注一下這其中'gt_overlaps'、'argmaxes'、'maxes'、'overlaps'、'I'的結構,對於理解這個函式費仲重要,最好在紙上寫出來~將RPN產生的proposal製作成roidb後,再回到rpn_roidb()中,使用merge_roidbs()將gt_roidb和rpn_roidb進行組合,見該函式:

這樣子就得到了最終訓練fast rcnn所需要的roidb資料,ok~再回到train_fast_rcnn()中,接著我們就來看看train_net()這個函式,進入該函式:

首先是使用filter_roidb()對之前產生的用於訓練fast_rcnn的roidb再進行一次篩選,具體過程參見該篩選函式:

篩選過之後,再回到train_net()函式中,建立一個solverWrapper物件,其中就是訓練得到的網路模型,進入這個類中:

上圖是它的類定義中的一部分,我們先來看看它的初始化函式,這裡需要注意的是add_bbox_regression_targets()這個函式,它的作用是為RPN產生的proposal提供迴歸屬性,該函式向roidb中再新增一個key:'bbox_targets',它的格式如:targets[][5]:第一個元素是label,後面四個元素就是論文中談及的tx,ty,tw,th;好的,我們進入這個函式:

上圖是改函式的前半部分,主要看_compute_targets()函式,它產生了迴歸屬性,進入該函式:

產生了迴歸屬性,OK,再回到add_bbox_regression_targets()函式中,看後面剩下的部分:

這部分主要得到rpn_roidb的座標的均值和方差,可以用來進行座標歸一化;OK,再回到SolverWrapper類中,剩下的則是snapshot快照方法,和train_model方法,回到train_net()函式中,接著再呼叫train_model()方法,進入該函式:

上圖的函式就是使用SGD得到訓練模型也就是我們需要的fast_rcnn網路模型,好了,train_net()函式就介紹到這兒了~

再回到train_fast_rcnn()函式中,剩下的都是儲存之類的,那我們再回到訓練流程中,剩下的幾步訓練流程就如法炮製了,見下:

這兩步訓練的網路結構見下圖:

這一步訓練的網路結構見下圖:

這樣子,就通過分步訓練得到了最終的網路模型,最後就是一些收尾工作了:

好了,終於全部弄完,接下來我們就來看作者在網路結構中新增的那幾層了~ 

http://www.cnblogs.com/zf-blog/p/7286405.html