開篇
? ? ? ? fasterrcnn網(wǎng)絡(luò)是接觸到的第一類目標(biāo)檢測網(wǎng)絡(luò),之前的RCNN-fastrcnn到現(xiàn)在的fasterrcnn。網(wǎng)絡(luò)上關(guān)于論文和網(wǎng)絡(luò)本身的代碼實現(xiàn)有非常多的介紹。我接觸目標(biāo)檢測時間不長,后面將會在較長的時間里一直做目標(biāo)檢測推理優(yōu)化的事情,所以學(xué)習(xí)一下幾個典型的網(wǎng)絡(luò)。本篇講述fasterrcnn,內(nèi)容大多都是網(wǎng)絡(luò)上的資源在此引用鏈接,學(xué)習(xí)各位大神的高見。
參考博客
https://blog.csdn.net/Gentleman_Qin/article/details/84403147
https://cloud.tencent.com/developer/article/1436272
https://zhuanlan.zhihu.com/p/31426458
*******************************************************************
論文
論文名稱:《?Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks 》
論文代碼:https://github.com/rbgirshick/py-faster-rcnn
卷積計算
********************************************************************
CNN普通卷積的輸出層大小計算公式:
假設(shè)
輸入數(shù)據(jù)維度為W*W
Filter大小?F×F
步長?S
padding的像素數(shù)?P
可以得出
N = (W ? F?+ 2P?)/S+1
輸出大小為?N×N
********************************************************************
網(wǎng)絡(luò)結(jié)構(gòu)


一、網(wǎng)絡(luò)結(jié)構(gòu)
對于提取候選框最常用的 SelectiveSearch 方法,提取一副圖像大概需要 2s 的時間,改進(jìn)的 EdgeBoxes 算法將效率提高到了 0.2s,但是這還不夠。
本文發(fā)現(xiàn)候選框提取不一定要在原圖上做,特征圖上同樣可以,低分辨率特征圖意味著更少的計算量,基于這個假設(shè)提出的RPN(RegionProposal Network),完美解決了這個問題。
Faster R-CNN可以簡單地看做“區(qū)域生成網(wǎng)絡(luò)RPNs + Fast R-CNN”的系統(tǒng),用區(qū)域生成網(wǎng)絡(luò)代替Fast R-CNN中的Selective Search方法。

通過添加額外的 RPN 分支網(wǎng)絡(luò),將候選框提取合并到深度網(wǎng)絡(luò)中,這正是 Faster-RCNN 里程碑式的貢獻(xiàn)。

RPN 網(wǎng)絡(luò)的特點(diǎn)在于通過滑動窗口的方式實現(xiàn)候選框的提取,每個滑動窗口位置生成 9 個候選窗口(不同尺度、不同寬高),提取對應(yīng) 9 個候選窗口(anchor)的特征,用于目標(biāo)分類和邊框回歸,與 FastRCNN 類似。

目標(biāo)分類只需要區(qū)分候選框內(nèi)特征為前景或者背景。
邊框回歸確定更精確的目標(biāo)位置,基本網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示:

訓(xùn)練過程中,涉及到的候選框選取,選取依據(jù):
1)丟棄跨越邊界的 anchor;
2)與樣本重疊區(qū)域大于 0.7 的 anchor 標(biāo)記為前景,重疊區(qū)域小于 0.3 的標(biāo)定為背景;
??????對于每一個位置,通過兩個全連接層(目標(biāo)分類 + 邊框回歸)對每個候選框(anchor)進(jìn)行判斷,并且結(jié)合概率值進(jìn)行舍棄(僅保留約 300 個 anchor),沒有顯式地提取任何候選窗口,完全使用網(wǎng)絡(luò)自身完成判斷和修正。
二、亮點(diǎn)解析
1、RoI Pooling:
? ? ? ? ?在 Faster RCNN中使用 RoI Pooling,以便使生成的候選框region proposal映射產(chǎn)生固定大小的feature map,進(jìn)行之后的分類和回歸。通過下圖解釋RoiPooling的工作原理:

(1)Conv layers使用的是VGG16,feat_stride=32(即表示,經(jīng)過網(wǎng)絡(luò)層后圖片縮小為原圖的1/32),原圖800*800,最后一層特征圖feature map大小:25*25;
(2)假定原圖中有一region proposal,大小為665*665,這樣,映射到特征圖中的大?。?65/32=20.78,即20.78*20.78,如果你看過Caffe的Roi Pooling的C++源碼,在計算的時候會進(jìn)行取整操作,于是,進(jìn)行所謂的第一次量化,即映射的特征圖大小為20*20;
(3)假定pooled_w=7,pooled_h=7,即pooling后固定成7*7大小的特征圖,所以,將上面在?feature map上映射的20*20的 region ?proposal劃分成49個同等大小的小區(qū)域,每個小區(qū)域的大小20/7=2.86,即2.86*2.86,此時,進(jìn)行第二次量化,故小區(qū)域大小變成2*2;
(4)每個2*2的小區(qū)域里,取出其中最大的像素值,作為這一個區(qū)域的‘代表’,這樣,49個小區(qū)域就輸出49個像素值,組成7*7大小的feature map;
? ? ? 總結(jié),通過上面可以看出,經(jīng)過兩次量化,即將浮點(diǎn)數(shù)取整,原本在特征圖上映射的20*20大小的region proposal,偏差成大小為14*14的,這樣的像素偏差勢必會對后層的回歸定位產(chǎn)生影響(?所以產(chǎn)生了替代方案,RoiAlign)。
2、RPN網(wǎng)絡(luò):

前面5層:
(1)首先,輸入圖片大小是 224*224*3(這個3是三個通道,也就是RGB三種);
(2)然后 layer1 的卷積核維度是 7*7*3*96 (所以大家要認(rèn)識到卷積核都是4維的,在caffe的矩陣計算中都是這么實現(xiàn)的);
(3)所以conv1得到的結(jié)果是110*110*96 (這個110來自于 (224-7+pad)/2 +1 ,這個pad是補(bǔ)零填充,也就是在圖片的周圍補(bǔ)充像素,這樣做的目的是為了能夠整除,除以2是因為2是圖中的stride, 這個計算方法在上面建議的文檔中有說明與推導(dǎo)的);
(4)然后做一次池化,得到pool1, 池化的核的大小是3*3,所以池化后圖片的維度是55*55*96 ?( ?(110-3+pad)/2 +1 =55 );
(5)然后接著就是再一次 layer2 卷積,這次的卷積核的維度是5*5*96*256 ,得到conv2:26*26*256;
(6)后面就是類似的過程,有些地方除法除不盡,作者做了填充,在caffe的prototxt文件中,可以看到每一層的pad的大??;
(7)最后作者取的是conv5的輸出,也就是13*13*256送給RPN網(wǎng)絡(luò)的;

RPN的原理:
1、前面我們指出,這個conv feature map的維度是13*13*256的;
2、作者在文章中指出,以3*3的正方形anchor為例,它作為sliding window的大小是3*3的,那么如何得到這個1*256的向量呢? 這個很簡單了,我們只需要一個3*3*256*256這樣的一個4維的卷積核,就可以將每一個3*3的sliding window 卷積成一個1*256的向量;
作者這里畫的示意圖 僅僅是 針對一個sliding window的;在實際實現(xiàn)中,我們有很多個sliding window,且大小不一, 即9中anchor,所以得到的并不是一維的256-d向量,實際上還是一個3維的矩陣數(shù)據(jù)結(jié)構(gòu);可能寫成for循環(huán)做sliding window大家會比較清楚,當(dāng)用矩陣運(yùn)算的時候,會稍微繞些;
3、然后就是k=9,所以cls layer就是18個輸出節(jié)點(diǎn)了,每個anchor生成一個2*1的向量,9個就是18*1。那么在256-d和cls layer之間使用一個1*1*256*2的卷積核,就可以得到一個anchor在一個位置上的對應(yīng)的cls layer,當(dāng)然這個1*1*256*2的卷積核就是大家平常理解的全連接;所以全連接只是卷積操作的一種特殊情況(當(dāng)卷積核的大小與圖片大小相同的時候,其實所謂的卷積就是全連接了,因為卷積核沒有做移動,所以其不包含圖像中個像素的相互之間的位置關(guān)系,這一點(diǎn)和FC層是一致的);
4、reg layer也是一樣了,reg layer的輸出是36個,所以對應(yīng)的卷積核是1*1*256*(36/9),這樣就可以得到reg layer的輸出了;
5、然后cls layer 和reg layer后面都會接到自己的損失函數(shù)上,給出損失函數(shù)的值,同時會根據(jù)求導(dǎo)的結(jié)果,給出反向傳播的數(shù)據(jù),這個過程讀者還是參考上面給的文檔,寫的挺清楚的;