點擊下方 卡片 ,關(guān)注“ 新機器視覺 ”公眾號
視覺/圖像重磅干貨,第一時間送達
本文從四個切入點為你介紹Faster R-CNN網(wǎng)絡。
經(jīng)過R-CNN和Fast RCNN的積淀,Ross B. Girshick在2016年提出了新的Faster RCNN,在結(jié)構(gòu)上,F(xiàn)aster RCNN已經(jīng)將特征抽取(feature extraction),proposal提取,bounding box regression(rect refine),classification都整合在了一個網(wǎng)絡中,使得綜合性能有較大提高,在檢測速度方面尤為明顯。
1 Conv layers 2 Region Proposal Networks(RPN) - 2.1 多通道圖像卷積基礎知識介紹 - 2.2 anchors - 2.3 softmax判定positive與negative - 2.4 bounding box regression原理 - 2.5 對proposals進行bounding box regression - 2.6 Proposal Layer3 RoI pooling - 3.1 為何需要RoI Pooling - 3.2 RoI Pooling原理4 Classification 5 Faster RCNN訓練 - 5.1 訓練RPN網(wǎng)絡 - 5.2 通過訓練好的RPN網(wǎng)絡收集proposals - 5.3 訓練Faster RCNN網(wǎng)絡Questions and Answer
圖1 Faster RCNN基本結(jié)構(gòu)(來自原論文)
依作者看來,如圖1,F(xiàn)aster RCNN其實可以分為4個主要內(nèi)容: Conv layers。作為一種CNN網(wǎng)絡目標檢測方法,F(xiàn)aster RCNN首先使用一組基礎的conv+relu+pooling層提取image的feature maps。該feature maps被共享用于后續(xù)RPN層和全連接層。 Region Proposal Networks。RPN網(wǎng)絡用于生成region proposals。該層通過softmax判斷anchors屬于positive或者negative,再利用bounding box regression修正anchors獲得精確的proposals。 Roi Pooling。該層收集輸入的feature maps和proposals,綜合這些信息后提取proposal feature maps,送入后續(xù)全連接層判定目標類別。 Classification。利用proposal feature maps計算proposal的類別,同時再次bounding box regression獲得檢測框最終的精確位置。 所以本文以上述4個內(nèi)容作為切入點介紹Faster R-CNN網(wǎng)絡。 圖2展示了python版本中的VGG16模型中的faster_rcnn_test.pt的網(wǎng)絡結(jié)構(gòu),可以清晰的看到該網(wǎng)絡對于一副任意大小PxQ的圖像: 首先縮放至固定大小MxN,然后將MxN圖像送入網(wǎng)絡; 而Conv layers中包含了13個conv層+13個relu層+4個pooling層; RPN網(wǎng)絡首先經(jīng)過3x3卷積,再分別生成positive anchors和對應bounding box regression偏移量,然后計算出proposals; 而Roi Pooling層則利用proposals從feature maps中提取proposal feature送入后續(xù)全連接和softmax網(wǎng)絡作classification(即分類proposal到底是什么object)。
圖2 faster_rcnn_test.pt網(wǎng)絡結(jié)構(gòu) (pascal_voc/VGG16/faster_rcnn_alt_opt/faster_rcnn_test.pt)
本文不會討論任何關(guān)于R-CNN家族的歷史,分析清楚最新的Faster R-CNN就夠了,并不需要追溯到那么久。實話說我也不了解R-CNN,更不關(guān)心。有空不如看看新算法。 新出爐的pytorch官方Faster RCNN代碼導讀:
捋一捋pytorch官方FasterRCNN代碼
https://zhuanlan.zhihu.com/p/31426458
1 Conv layers
Conv layers包含了conv,pooling,relu三種層。以python版本中的VGG16模型中的faster_rcnn_test.pt的網(wǎng)絡結(jié)構(gòu)為例,如圖2,Conv layers部分共有13個conv層,13個relu層,4個pooling層。這里有一個非常容易被忽略但是又無比重要的信息,在Conv layers中: 所有的conv層都是:kernel_size=3,pad=1,stride=1 所有的pooling層都是:kernel_size=2,pad=0,stride=2 為何重要?在Faster RCNN Conv layers中對所有的卷積都做了擴邊處理( pad=1,即填充一圈0),導致原圖變?yōu)?(M+2)x(N+2)大小,再做3x3卷積后輸出MxN 。正是這種設置,導致Conv layers中的conv層不改變輸入和輸出矩陣大小。如圖3:
類似的是,Conv layers中的pooling層kernel_size=2,stride=2。這樣每個經(jīng)過pooling層的MxN矩陣,都會變?yōu)?M/2)x(N/2)大小。綜上所述,在整個Conv layers中,conv和relu層不改變輸入輸出大小,只有pooling層使輸出長寬都變?yōu)檩斎氲?/2。 那么,一個MxN大小的矩陣經(jīng)過Conv layers固定變?yōu)?M/16)x(N/16)!這樣Conv layers生成的feature map中都可以和原圖對應起來。 2 Region Proposal Networks(RPN)
經(jīng)典的檢測方法生成檢測框都非常耗時,如OpenCV adaboost使用滑動窗口+圖像金字塔生成檢測框;或如R-CNN使用SS(Selective Search)方法生成檢測框。而Faster RCNN則拋棄了傳統(tǒng)的滑動窗口和SS方法,直接使用RPN生成檢測框,這也是Faster R-CNN的巨大優(yōu)勢,能極大提升檢測框的生成速度。
圖4 RPN網(wǎng)絡結(jié)構(gòu)
上圖4展示了RPN網(wǎng)絡的具體結(jié)構(gòu)。可以看到RPN網(wǎng)絡實際分為2條線,上面一條通過softmax分類anchors獲得positive和negative分類,下面一條用于計算對于anchors的bounding box regression偏移量,以獲得精確的proposal。而最后的Proposal層則負責綜合positive anchors和對應bounding box regression偏移量獲取proposals,同時剔除太小和超出邊界的proposals。其實整個網(wǎng)絡到了Proposal Layer這里,就完成了相當于目標定位的功能。 2.1 多通道圖像卷積基礎知識介紹
在介紹RPN前,還要多解釋幾句基礎知識,已經(jīng)懂的看官老爺跳過就好。 對于單通道圖像+單卷積核做卷積,第一章中的圖3已經(jīng)展示了;
如圖5,輸入有3個通道,同時有2個卷積核。對于每個卷積核,先在輸入3個通道分別作卷積,再將3個通道結(jié)果加起來得到卷積輸出。所以對于某個卷積層,無論輸入圖像有多少個通道,輸出圖像通道數(shù)總是等于卷積核數(shù)量! 對多通道圖像做1x1卷積,其實就是將輸入圖像于每個通道乘以卷積系數(shù)后加在一起,即相當于把原圖像中本來各個獨立的通道“聯(lián)通”在了一起。 2.2 anchors
提到RPN網(wǎng)絡,就不能不說anchors。所謂anchors,實際上就是一組由rpn/generate_anchors.py生成的矩形。直接運行作者demo中的generate_anchors.py可以得到以下輸出: [[ -84. -40. 99. 55. ] [-176. -88. 191. 103. ] [-360. -184. 375. 199. ] [ -56. -56. 71. 71. ] [-120. -120. 135. 135. ] [-248. -248. 263. 263. ] [ -36. -80. 51. 95. ] [ -80. -168. 95. 183. ] [-168. -344. 183. 359. ]] 其中每行的4個值 表矩形左上和右下角點坐標。9個矩形共有3種形狀,長寬比為大約為 三種,如圖6。實際上通過anchors就引入了檢測中常用到的多尺度方法。
注:關(guān)于上面的anchors size,其實是根據(jù)檢測圖像設置的。在python demo中,會把任意大小的輸入圖像reshape成800x600(即圖2中的M=800,N=600)。再回頭來看anchors的大小,anchors中長寬1:2中最大為352x704,長寬2:1中最大736x384,基本是cover了800x600的各個尺度和形狀。 那么這9個anchors是做什么的呢?借用Faster RCNN論文中的原圖,如圖7,遍歷Conv layers計算獲得的feature maps,為每一個點都配備這9種anchors作為初始的檢測框。這樣做獲得檢測框很不準確,不用擔心,后面還有2次bounding box regression可以修正檢測框位置。
在原文中使用的是ZF model中,其Conv Layers中最后的conv5層num_output=256,對應生成256張?zhí)卣鲌D,所以相當于feature map每個點都是256-dimensions 在conv5之后,做了rpn_conv/3x3卷積且num_output=256,相當于每個點又融合了周圍3x3的空間信息(猜測這樣做也許更魯棒?反正我沒測試),同時256-d不變(如圖4和圖7中的紅框) 假設在conv5 feature map中每個點上有k個anchor(默認k=9),而每個anhcor要分positive和negative,所以每個點由256d feature轉(zhuǎn)化為cls=2?k scores;而每個anchor都有(x, y, w, h)對應4個偏移量,所以reg=4?k coordinates 補充一點,全部anchors拿去訓練太多了,訓練程序會在合適的anchors中隨機選取128個postive anchors+128個negative anchors進行訓練(什么是合適的anchors下文5.1有解釋) 注意,在本文講解中使用的VGG conv5 num_output=512,所以是512d,其他類似。 其實RPN最終就是在原圖尺度上,設置了密密麻麻的候選Anchor。然后用cnn去判斷哪些Anchor是里面有目標的positive anchor,哪些是沒目標的negative anchor。所以,僅僅是個二分類而已! 那么Anchor一共有多少個?原圖800x600,VGG下采樣16倍,feature map每個點設置9個Anchor,所以:
其中ceil()表示向上取整,是因為VGG輸出的feature map size= 50*38。
2.3 softmax判定positive與negative
一副MxN大小的矩陣送入Faster RCNN網(wǎng)絡后,到RPN網(wǎng)絡變?yōu)?M/16)x(N/16),不妨設 W=M/16,H=N/16。在進入reshape與softmax之前,先做了1x1卷積,如圖9:
圖9 RPN中判定positive/negative網(wǎng)絡結(jié)構(gòu)
該1x1卷積的caffe prototxt定義如下: layer { name: "rpn_cls_score" type: "Convolution" bottom: "rpn/output" top: "rpn_cls_score" convolution_param { num_output: 18 # 2(positive/negative) * 9(anchors) kernel_size: 1 pad: 0 stride: 1 } } 可以看到其num_output=18,也就是經(jīng)過該卷積的輸出圖像為WxHx18大小(注意第二章開頭提到的卷積計算方式)。這也就剛好對應了feature maps每一個點都有9個anchors,同時每個anchors又有可能是positive和negative,所有這些信息都保存WxHx(9*2)大小的矩陣。為何這樣做?后面接softmax分類獲得positive anchors,也就相當于初步提取了檢測目標候選區(qū)域box(一般認為目標在positive anchors中)。 那么為何要在softmax前后都接一個reshape layer?其實只是為了便于softmax分類,至于具體原因這就要從caffe的實現(xiàn)形式說起了。在caffe基本數(shù)據(jù)結(jié)構(gòu)blob中以如下形式保存數(shù)據(jù): blob =[batch_size, channel,height,width]
對應至上面的保存positive/negative anchors的矩陣,其在caffe blob中的存儲形式為[1, 2x9, H, W]。而在softmax分類時需要進行positive/negative二分類,所以reshape layer會將其變?yōu)閇1, 2, 9xH, W]大小,即單獨“騰空”出來一個維度以便softmax分類,之后再reshape回復原狀。貼一段caffe softmax_loss_layer.cpp的reshape函數(shù)的解釋,非常精辟:
"Number of labels must match number of predictions; " "e.g., if softmax axis == 1 and prediction shape is (N, C, H, W), " "label count (number of labels) must be N*H*W, " "with integer values in {0, 1, ..., C-1}."; 綜上所述,RPN網(wǎng)絡中利用anchors和softmax初步提取出positive anchors作為候選區(qū)域(另外也有實現(xiàn)用sigmoid代替softmax,輸出[1, 1, 9xH, W]后接sigmoid進行positive/negative二分類,原理一樣)。 2.4 bounding box regression原理
如圖9所示綠色框為飛機的Ground Truth(GT),紅色為提取的positive anchors,即便紅色的框被分類器識別為飛機,但是由于紅色的框定位不準,這張圖相當于沒有正確的檢測出飛機。所以我們希望采用一種方法對紅色的框進行微調(diào),使得positive anchors和GT更加接近。
對于窗口一般使用四維向量 表示,分別表示窗口的中心點坐標和寬高。對于圖 11,紅色的框A代表原始的positive Anchors,綠色的框G代表目標的GT,我們的目標是尋找一種關(guān)系,使得輸入原始的anchor A經(jīng)過映射得到一個跟真實窗口G更接近的回歸窗口G',即: 給定anchor ;尋找一種變換F,使得: ,其中 。
那么經(jīng)過何種變換F才能從圖10中的anchor A變?yōu)镚'呢?比較簡單的思路就是:
觀察上面4個公式發(fā)現(xiàn),需要學習的是 這四個變換。當輸入的anchor A與GT相差較小時,可以認為這種變換是一種線性變換, 那么就可以用線性回歸來建模對窗口進行微調(diào)(注意,只有當anchors A和GT比較接近時,才能使用線性回歸模型,否則就是復雜的非線性問題了)。 接下來的問題就是如何通過線性回歸獲得 了。線性回歸就是給定輸入的特征向量X, 學習一組參數(shù)W, 使得經(jīng)過線性回歸后的值跟真實值Y非常接近,即Y=WX。對于該問題,輸入X是cnn feature map,定義為Φ;同時還有訓練傳入A與GT之間的變換量,即 。輸出是 四個變換。那么目標函數(shù)可以表示為:
其中 是對應anchor的feature map組成的特征向量, 是需要學習的參數(shù), 是得到的預測值(*表示 x,y,w,h,也就是每一個變換對應一個上述目標函數(shù))。為了讓預測值 與真實值 差距最小,設計L1損失函數(shù):
為了方便描述,這里以L1損失為例介紹,而真實情況中一般使用soomth-L1損失。 需要說明,只有在GT與需要回歸框位置比較接近時,才可近似認為上述線性變換成立。 說完原理,對應于Faster RCNN原文,positive anchor與ground truth之間的平移量 與尺度因子 如下:
對于訓練bouding box regression網(wǎng)絡回歸分支,輸入是cnn feature Φ,監(jiān)督信號是Anchor與GT的差距 ,即訓練目標是:輸入 Φ的情況下使網(wǎng)絡輸出與監(jiān)督信號盡可能接近。那么當bouding box regression工作時,再輸入Φ時,回歸網(wǎng)絡分支的輸出就是每個Anchor的平移量和變換尺度 ,顯然即可用來修正Anchor位置了。 2.5 對proposals進行bounding box regression
在了解bounding box regression后,再回頭來看RPN網(wǎng)絡第二條線路,如圖12。
先來看一看上圖11中1x1卷積的caffe prototxt定義: layer { name: "rpn_bbox_pred" type: "Convolution" bottom: "rpn/output" top: "rpn_bbox_pred" convolution_param { num_output: 36 # 4 * 9(anchors) kernel_size: 1 pad: 0 stride: 1 } } 可以看到其 num_output=36,即經(jīng)過該卷積輸出圖像為WxHx36,在caffe blob存儲為[1, 4x9, H, W],這里相當于feature maps每個點都有9個anchors,每個anchors又都有4個用于回歸的 變換量。 回到圖8,VGG輸出 50*38*512 的特征,對應設置 50*38*k 個anchors,而RPN輸出: 大小為 50*38*2k 的positive/negative softmax分類特征矩陣; 大小為 50*38*4k 的regression坐標回歸特征矩陣。 恰好滿足RPN完成positive/negative分類+bounding box regression坐標回歸。 2.6 Proposal Layer
Proposal Layer負責綜合所有 變換量和positive anchors,計算出精準的proposal,送入后續(xù)RoI Pooling Layer。還是先來看看Proposal Layer的caffe prototxt定義: layer { name: 'proposal' type: 'Python' bottom: 'rpn_cls_prob_reshape' bottom: 'rpn_bbox_pred' bottom: 'im_info' top: 'rois' python_param { module: 'rpn.proposal_layer' layer: 'ProposalLayer' param_str: "'feat_stride': 16" } } Proposal Layer有3個輸入:positive vs negative anchors分類器結(jié)果rpn_cls_prob_reshape,對應的bbox reg的 變換量rpn_bbox_pred,以及im_info;另外還有參數(shù)feat_stride=16,這和圖4是對應的。 首先解釋im_info。對于一副任意大小PxQ圖像,傳入Faster RCNN前首先reshape到固定MxN,im_info=[M, N, scale_factor]則保存了此次縮放的所有信息。然后經(jīng)過Conv Layers,經(jīng)過4次pooling變?yōu)閃xH=(M/16)x(N/16)大小,其中feature_stride=16則保存了該信息,用于計算anchor偏移量。
Proposal Layer forward(caffe layer的前傳函數(shù))按照以下順序依次處理: 生成anchors,利用對所有的anchors做bbox regression回歸(這里的anchors生成和訓練時完全一致) ;按照輸入的positive softmax scores由大到小排序anchors,提取前pre_nms_topN(e.g. 6000)個anchors,即提取修正位置后的positive anchors; 限定超出圖像邊界的positive anchors為圖像邊界,防止后續(xù)roi pooling時proposal超出圖像邊界(見文章底部QA部分圖21); 剔除尺寸非常小的positive anchors; 對剩余的positive anchors進行NMS(nonmaximum suppression) Proposal Layer有3個輸入:positive和negative anchors分類器結(jié)果rpn_cls_prob_reshape,對應的bbox reg的(e.g. 300)結(jié)果作為proposal輸出。 之后輸出proposal=[x1, y1, x2, y2],注意,由于在第三步中將anchors映射回原圖判斷是否超出邊界,所以這里輸出的proposal是對應MxN輸入圖像尺度的,這點在后續(xù)網(wǎng)絡中有用。另外我認為,嚴格意義上的檢測應該到此就結(jié)束了,后續(xù)部分應該屬于識別了。 RPN網(wǎng)絡結(jié)構(gòu)就介紹到這里,總結(jié)起來就是: 生成anchors -> softmax分類器提取positvie anchors -> bbox reg回歸positive anchors -> Proposal Layer生成proposals 3 RoI pooling
而RoI Pooling層則負責收集proposal,并計算出proposal feature maps,送入后續(xù)網(wǎng)絡。從圖2中可以看到Rol pooling層有2個輸入: RPN輸出的proposal boxes(大小各不相同) 3.1 為何需要RoI Pooling
先來看一個問題:對于傳統(tǒng)的CNN(如AlexNet和VGG),當網(wǎng)絡訓練好后輸入的圖像尺寸必須是固定值,同時網(wǎng)絡輸出也是固定大小的vector or matrix。如果輸入圖像大小不定,這個問題就變得比較麻煩。有2種解決辦法: 將圖像warp成需要的大小后傳入網(wǎng)絡。
圖14 crop與warp破壞圖像原有結(jié)構(gòu)信息
兩種辦法的示意圖如圖14,可以看到無論采取那種辦法都不好,要么crop后破壞了圖像的完整結(jié)構(gòu),要么warp破壞了圖像原始形狀信息。 回憶RPN網(wǎng)絡生成的proposals的方法:對positive anchors進行bounding box regression,那么這樣獲得的proposals也是大小形狀各不相同,即也存在上述問題。所以Faster R-CNN中提出了RoI Pooling解決這個問題。不過RoI Pooling確實是從Spatial Pyramid Pooling發(fā)展而來,但是限于篇幅這里略去不講,有興趣的讀者可以自行查閱相關(guān)論文。 3.2 RoI Pooling原理 分析之前先來看看RoI Pooling Layer的caffe prototxt的定義: layer { name: "roi_pool5" type: "ROIPooling" bottom: "conv5_3" bottom: "rois" top: "pool5" roi_pooling_param { pooled_w: 7 pooled_h: 7 spatial_scale: 0.0625 # 1/16 } } 其中有新參數(shù)pooled_w和pooled_h,另外一個參數(shù)spatial_scale認真閱讀的讀者肯定已經(jīng)知道知道用途。RoI Pooling layer forward過程: 由于proposal是對應MxN尺度的,所以首先使用spatial_scale參數(shù)將其映射回(M/16)x(N/16)大小的feature map尺度; 再將每個proposal對應的feature map區(qū)域水平分為pooled_w x pooled_h 的網(wǎng)格; 對網(wǎng)格的每一份都進行max pooling處理。 這樣處理后,即使大小不同的proposal輸出結(jié)果都是 pooled_w x pooled_h 固定大小,實現(xiàn)了固定長度輸出。
4 Classification
Classification部分利用已經(jīng)獲得的proposal feature maps,通過full connect層與softmax計算每個proposal具體屬于那個類別(如人,車,電視等),輸出cls_prob概率向量;同時再次利用bounding box regression獲得每個proposal的位置偏移量bbox_pred,用于回歸更加精確的目標檢測框。Classification部分網(wǎng)絡結(jié)構(gòu)如圖16。
圖16 Classification部分網(wǎng)絡結(jié)構(gòu)圖
從RoI Pooling獲取到7x7=49大小的proposal feature maps后,送入后續(xù)網(wǎng)絡,可以看到做了如下2件事: 通過全連接和softmax對proposals進行分類,這實際上已經(jīng)是識別的范疇了; 再次對proposals進行bounding box regression,獲取更高精度的rect box。 這里來看看全連接層InnerProduct layers,簡單的示意圖如圖17:
其中W和bias B都是預先訓練好的,即大小是固定的,當然輸入X和輸出Y也就是固定大小。所以,這也就印證了之前Roi Pooling的必要性。到這里,我想其他內(nèi)容已經(jīng)很容易理解,不在贅述了。 5 Faster RCNN訓練
Faster R-CNN的訓練,是在已經(jīng)訓練好的model(如VGG_CNN_M_1024,VGG,ZF)的基礎上繼續(xù)進行訓練。實際中訓練過程分為6個步驟: 在已經(jīng)訓練好的model上,訓練RPN網(wǎng)絡,對應stage1_rpn_train.pt 利用步驟1中訓練好的RPN網(wǎng)絡,收集proposals,對應rpn_test.pt 第一次訓練Fast RCNN網(wǎng)絡,對應stage1_fast_rcnn_train.pt 第二訓練RPN網(wǎng)絡,對應stage2_rpn_train.pt 再次利用步驟4中訓練好的RPN網(wǎng)絡,收集proposals,對應rpn_test.pt 第二次訓練Fast RCNN網(wǎng)絡,對應stage2_fast_rcnn_train.pt 可以看到訓練過程類似于一種“迭代”的過程,不過只循環(huán)了2次。至于只循環(huán)了2次的原因是應為作者提到:"A similar alternating training can be run for more iterations, but we have observed negligible improvements",即循環(huán)更多次沒有提升了。接下來本章以上述6個步驟講解訓練過程。
5.1 訓練RPN網(wǎng)絡 在該步驟中,首先讀取RBG提供的預訓練好的model(本文使用VGG),開始迭代訓練。來看看stage1_rpn_train.pt網(wǎng)絡結(jié)構(gòu),如圖19。
圖19 stage1_rpn_train.pt(考慮圖片大小,Conv Layers中所有的層都畫在一起了,如紅圈所示,后續(xù)圖都如此處理)
與檢測網(wǎng)絡類似的是,依然使用Conv Layers提取feature maps。整個網(wǎng)絡使用的Loss如下:
上述公式中 i 表示anchors index, 表示positive softmax probability, 代表對應的GT predict概率(即當?shù)趇個anchor與GT間IoU>0.7,認為是該anchor是positive, ;反之IoU<0.3時,認為是該anchor是negative, ;至于那些0.3<IoU<0.7的anchor則不參與訓練);t代表predict bounding box,t* 代表對應positive anchor對應的GT box。可以看到,整個Loss分為2部分: cls loss,即rpn_cls_loss層計算的softmax loss,用于分類anchors為positive與negative的網(wǎng)絡訓練; reg loss,即rpn_loss_bbox層計算的soomth L1 loss,用于bounding box regression網(wǎng)絡訓練。注意在該loss中乘了 ,相當于只關(guān)心positive anchors的回歸(其實在回歸中也完全沒必要去關(guān)心negative)。 由于在實際過程中, 和 差距過大,用參數(shù)λ平衡二者(如 , 時設置 ),使總的網(wǎng)絡Loss計算過程中能夠均勻考慮2種Loss。這里比較重要是 使用的soomth L1 loss,計算公式如下:
在RPN訓練階段,rpn-data(python AnchorTargetLayer)層會按照和test階段Proposal層完全一樣的方式生成Anchors用于訓練; 對于rpn_loss_cls,輸入的rpn_cls_scors_reshape和rpn_labels分別對應 與 ,參數(shù)隱含在 與 的caffe blob的大小中; 對于rpn_loss_bbox,輸入的rpn_bbox_pred和rpn_bbox_targets分別對應 t 與 t* ,rpn_bbox_inside_weigths對應 ,rpn_bbox_outside_weigths未用到(從smooth_L1_Loss layer代碼中可以看到),而 同樣隱含在caffe blob大小中。 這樣,公式與代碼就完全對應了。特別需要注意的是,在訓練和檢測階段生成和存儲anchors的順序完全一樣,這樣訓練結(jié)果才能被用于檢測! 5.2 通過訓練好的RPN網(wǎng)絡收集proposals
在該步驟中,利用之前的RPN網(wǎng)絡,獲取proposal rois,同時獲取positive softmax probability,如圖20,然后將獲取的信息保存在python pickle文件中。該網(wǎng)絡本質(zhì)上和檢測中的RPN網(wǎng)絡一樣,沒有什么區(qū)別。
5.3 訓練Faster RCNN網(wǎng)絡
讀取之前保存的pickle文件,獲取proposals與positive probability。從data層輸入網(wǎng)絡。然后: 將提取的proposals作為rois傳入網(wǎng)絡,如圖21藍框; 計算bbox_inside_weights+bbox_outside_weights,作用與RPN一樣,傳入soomth_L1_loss layer,如圖21綠框。 這樣就可以訓練最后的識別softmax與最終的bounding box regression了。
圖21 stage1_fast_rcnn_train.pt
之后的stage2訓練都是大同小異,不再贅述了。Faster R-CNN還有一種end-to-end的訓練方式,可以一次完成train,有興趣請自己看作者GitHub吧。 rbgirshick py-faster-rcn: github.com/rbgirshick/py-faster-rcnn Q&A
此篇文章初次成文于2016年內(nèi)部學習分享,再后來經(jīng)多次修正和完善成為現(xiàn)在的樣子。感謝大家一直以來的支持,現(xiàn)在總結(jié)常見疑問回答如下: 回顧anchor生成步驟:首先生成9個base anchor,然后通過坐標偏移在50*38 大小的 1/16下采樣FeatureMap每個點都放上這9個base anchor,就形成了 50*38*k 個anhcors。至于這9個base anchor坐標是什么其實并不重要,不同代碼實現(xiàn)也許不同。 顯然這里面有一部分邊緣anchors會超出圖像邊界,而真實中不會有超出圖像的目標,所以會有clip anchor步驟。
VGG輸出 50*38*512 的特征,對應設置 50*38*k 個anchors,而RPN輸出 50*38*2k 的分類特征矩陣和 50*38*4k 的坐標回歸特征矩陣。
圖22 anchor與網(wǎng)絡輸出如何對應方式
其實在實現(xiàn)過程中,每個點的 2k 個分類特征與 4k 回歸特征,與 k 個anchor逐個對應即可,這實際是一種“人為設置的邏輯映射”。當然,也可以不這樣設置,但是無論如何都需要保證在訓練和測試過程中映射方式必須一致 。 為何有ROI Pooling還要把輸入圖片resize到固定大小的MxN? 由于引入ROI Pooling,從原理上說Faster R-CNN確實能夠檢測任意大小的圖片。但是由于在訓練的時候需要使用大batch訓練網(wǎng)絡,而不同大小輸入拼batch在實現(xiàn)的時候代碼較為復雜,而且當時以Caffe為代表的第一代深度學習框架也不如Tensorflow和PyTorch靈活,所以作者選擇了把輸入圖片resize到固定大小的800x600。這應該算是歷史遺留問題。 另外很多問題,都是屬于具體實現(xiàn)問題,真誠的建議讀者閱讀代碼自行理解。 拓展
請問目標檢測中的detection performance一般是指那個指標,還是一個統(tǒng)稱? https://www.zhihu.com/question/288198143/answer/482600906 Faster RCNN在文字檢測中的應用:CTPN https://zhuanlan.zhihu.com/p/34757009 https://mp.weixin.qq.com/s/IJUMCOBhgXHv7VC1YT4q_g 本文章只是介紹和分析原論文的思路,原文和代碼怎么說我就怎么寫,所以不涉及改進等內(nèi)容。如對FasterRCNN論文和原代碼有意見,建議向原作者詢問,謝謝。 轉(zhuǎn)自 | 一文讀懂Faster RCNN https://zhuanlan.zhihu.com/p/31426458