日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

rcnn -fast rcnn-faster rcnn物体检测论文

發(fā)布時(shí)間:2023/12/20 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 rcnn -fast rcnn-faster rcnn物体检测论文 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

faster rcnn中的rpn網(wǎng)絡(luò):

特征可以看做一個(gè)尺度51*39的256通道圖像,對(duì)于該圖像的每一個(gè)位置,考慮9個(gè)可能的候選窗口:三種面積{1282,2562,5122}×三種比例{1:1,1:2,2:1}。這些候選窗口稱為anchors。下圖示出51*39個(gè)anchor中心,以及9種anchor示例。?

講解RPN網(wǎng)絡(luò)比較好的博客:https://blog.csdn.net/sloanqin/article/details/51545125

RCNN的缺點(diǎn):

1、圖像wrap的問題

2、計(jì)算量大

?

FAST RCNN

1、ROI pooling就是不同大小feature resize到一個(gè)固定大小

2、Train end to end,multi task loss

梯度如何從唯一大小回傳到任意大小,如果有影響,相當(dāng)于y=x,如果有影響就累加

?

FASTER RCNN

1、test的時(shí)候要做NMS,RPN

2、Joint trainning

?

?

?

?

?

?

?

?

?

?

首先rcnn,和fast rcnn都比較好理解

fast rcnn其實(shí)就是roi+clc+bbox regression

faster rcnn是rpn(region proposal network)+ fast rcnn,最后兩個(gè)網(wǎng)絡(luò)是迭代訓(xùn)練

本弱找到一篇講解faster rcnn比較好都博文,所以就速速搬過來了:

縮進(jìn)經(jīng)過RCNN和Fast RCNN的積淀,Ross B. Girshick在2016年提出了新的Faster RCNN,在結(jié)構(gòu)上,Faster RCN已經(jīng)將特征抽取(feature extraction),proposal提取,bounding box regression(rect refine),classification都整合在了一個(gè)網(wǎng)絡(luò)中,使得綜合性能有較大提高,在檢測(cè)速度方面尤為明顯。

圖1 Faster CNN基本結(jié)構(gòu)(來自原論文)

縮進(jìn)依作者看來,如圖1,Faster RCNN其實(shí)可以分為4個(gè)主要內(nèi)容:

?

  • Conv layers。作為一種CNN網(wǎng)絡(luò)目標(biāo)檢測(cè)方法,Faster RCNN首先使用一組基礎(chǔ)的conv+relu+pooling層提取image的feature maps。該feature maps被共享用于后續(xù)RPN層和全連接層。
  • Region Proposal Networks。RPN網(wǎng)絡(luò)用于生成region proposals。該層通過softmax判斷anchors屬于foreground或者background,再利用bounding box regression修正anchors獲得精確的proposals。
  • Roi Pooling。該層收集輸入的feature maps和proposals,綜合這些信息后提取proposal?feature maps,送入后續(xù)全連接層判定目標(biāo)類別。
  • Classification。利用proposal?feature maps計(jì)算proposal的類別,同時(shí)再次bounding box regression獲得檢測(cè)框最終的精確位置。
  • 所以本文以上述4個(gè)內(nèi)容作為切入點(diǎn)介紹Faster RCNN網(wǎng)絡(luò)。

    縮進(jìn)圖2展示了Python版本中的VGG16模型中的faster_rcnn_test.pt的網(wǎng)絡(luò)結(jié)構(gòu),可以清晰的看到該網(wǎng)絡(luò)對(duì)于一副任意大小PxQ的圖像,首先縮放至固定大小MxN,然后將MxN圖像送入網(wǎng)絡(luò);而Conv layers中包含了13個(gè)conv層+13個(gè)relu層+4個(gè)pooling層;RPN網(wǎng)絡(luò)首先經(jīng)過3x3卷積,再分別生成foreground anchors與bounding box regression偏移量,然后計(jì)算出proposals;而Roi Pooling層則利用proposals從feature maps中提取proposal feature送入后續(xù)全連接和softmax網(wǎng)絡(luò)作classification(即分類proposal到底是什么object)。

    path:${py-faster-rcnn-root}/models/pascal_voc/VGG16/faster_rcnn_alt_opt/faster_rcnn_test.pt

    圖2 faster_rcnn_test.pt網(wǎng)絡(luò)結(jié)構(gòu)(放大網(wǎng)頁看大圖)

    1 Conv layers

    縮進(jìn)Conv layers包含了conv,pooling,relu三種層。以python版本中的VGG16模型中的faster_rcnn_test.pt的網(wǎng)絡(luò)結(jié)構(gòu)為例,如圖2,Conv layers部分共有13個(gè)conv層,13個(gè)relu層,4個(gè)pooling層。這里有一個(gè)非常容易被忽略但是又無比重要的信息,在Conv layers中:

  • 所有的conv層都是:kernel_size=3,pad=1
  • 所有的pooling層都是:kernel_size=2,stride=2
  • 為何重要?在Faster RCNN Conv layers中對(duì)所有的卷積都做了擴(kuò)邊處理(pad=1,即填充一圈0),導(dǎo)致原圖變?yōu)?M+2)x(N+2)大小,再做3x3卷積后輸出MxN。正是這種設(shè)置,導(dǎo)致Conv layers中的conv層不改變輸入和輸出矩陣大小。如圖3:

    圖3

    類似的是,Conv layers中的pooling層kernel_size=2,stride=2。這樣每個(gè)經(jīng)過pooling層的MxN矩陣,都會(huì)變?yōu)?M/2)*(N/2)大小。綜上所述,在整個(gè)Conv layers中,conv和relu層不改變輸入輸出大小,只有pooling層使輸出長(zhǎng)寬都變?yōu)檩斎氲?/2。

    縮進(jìn)那么,一個(gè)MxN大小的矩陣經(jīng)過Conv layers固定變?yōu)?M/16)x(N/16)!這樣Conv layers生成的featuure map中都可以和原圖對(duì)應(yīng)起來。

    ?

    2 Region Proposal Networks(RPN)

    縮進(jìn)經(jīng)典的檢測(cè)方法生成檢測(cè)框都非常耗時(shí),如OpenCV?adaboost使用滑動(dòng)窗口+圖像金字塔生成檢測(cè)框;或如RCNN使用SS(Selective Search)方法生成檢測(cè)框。而Faster RCNN則拋棄了傳統(tǒng)的滑動(dòng)窗口和SS方法,直接使用RPN生成檢測(cè)框,這也是Faster RCNN的巨大優(yōu)勢(shì),能極大提升檢測(cè)框的生成速度。

    圖4 RPN網(wǎng)絡(luò)結(jié)構(gòu)

    上圖4展示了RPN網(wǎng)絡(luò)的具體結(jié)構(gòu)。可以看到RPN網(wǎng)絡(luò)實(shí)際分為2條線,上面一條通過softmax分類anchors獲得foreground和background(檢測(cè)目標(biāo)是foreground),下面一條用于計(jì)算對(duì)于anchors的bounding box regression偏移量,以獲得精確的proposal。而最后的Proposal層則負(fù)責(zé)綜合foreground anchors和bounding box regression偏移量獲取proposals,同時(shí)剔除太小和超出邊界的proposals。其實(shí)整個(gè)網(wǎng)絡(luò)到了Proposal Layer這里,就完成了相當(dāng)于目標(biāo)定位的功能。

    2.1 多通道圖像卷積基礎(chǔ)知識(shí)介紹

    縮進(jìn)在介紹RPN前,還要多解釋幾句基礎(chǔ)知識(shí),已經(jīng)懂的看官老爺跳過就好。
  • 對(duì)于單通道圖像+單卷積核做卷積,第一章中的圖3已經(jīng)展示了;
  • 對(duì)于多通道圖像+多卷積核做卷積,計(jì)算方式如下:
  • 圖5 多通道+多卷積核做卷積示意圖(摘自Theano教程) 縮進(jìn)如圖5,輸入圖像layer m-1有4個(gè)通道,同時(shí)有2個(gè)卷積核w1和w2。對(duì)于卷積核w1,先在輸入圖像4個(gè)通道分別作卷積,再將4個(gè)通道結(jié)果加起來得到w1的卷積輸出;卷積核w2類似。所以對(duì)于某個(gè)卷積層,無論輸入圖像有多少個(gè)通道,輸出圖像通道數(shù)總是等于卷積核數(shù)量! 縮進(jìn)對(duì)多通道圖像做1x1卷積,其實(shí)就是將輸入圖像于每個(gè)通道乘以卷積系數(shù)后加在一起,即相當(dāng)于把原圖像中本來各個(gè)獨(dú)立的通道“聯(lián)通”在了一起。

    2.2 anchors

    縮進(jìn)提到RPN網(wǎng)絡(luò),就不能不說anchors。所謂anchors,實(shí)際上就是一組由rpn/generate_anchors.py生成的矩形。直接運(yùn)行作者demo中的generate_anchors.py可以得到以下輸出:

    [python]?view plaincopy
  • [[?-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個(gè)值[x1,y1,x2,y2]代表矩形左上和右下角點(diǎn)坐標(biāo)。9個(gè)矩形共有3種形狀,長(zhǎng)寬比為大約為:width:height = [1:1, 1:2, 2:1]三種,如圖6。實(shí)際上通過anchors就引入了檢測(cè)中常用到的多尺度方法。

    圖6 anchors示意圖

    注:關(guān)于上面的anchors size,其實(shí)是根據(jù)檢測(cè)圖像設(shè)置的。在python demo中,會(huì)把任意大小的輸入圖像reshape成800x600(即圖2中的M=800,N=600)。再回頭來看anchors的大小,anchors中長(zhǎng)寬1:2中最大為352x704,長(zhǎng)寬2:1中最大736x384,基本是cover了800x600的各個(gè)尺度和形狀。

    那么這9個(gè)anchors是做什么的呢?借用Faster RCNN論文中的原圖,如圖7,遍歷Conv layers計(jì)算獲得的feature maps,為每一個(gè)點(diǎn)都配備這9種anchors作為初始的檢測(cè)框。這樣做獲得檢測(cè)框很不準(zhǔn)確,不用擔(dān)心,后面還有2次bounding box regression可以修正檢測(cè)框位置。

    圖7

    解釋一下上面這張圖的數(shù)字。

  • 在原文中使用的是ZF model中,其Conv Layers中最后的conv5層num_output=256,對(duì)應(yīng)生成256張?zhí)卣鲌D,所以相當(dāng)于feature map每個(gè)點(diǎn)都是256-d
  • 在conv5之后,做了rpn_conv/3x3卷積且num_output=256,相當(dāng)于每個(gè)點(diǎn)又融合了周圍3x3的空間信息(猜測(cè)這樣做也許更魯棒?反正我沒測(cè)試),同時(shí)256-d不變(如圖4和圖7中的紅框)
  • 假設(shè)一共有k個(gè)anchor,而每個(gè)anhcor要分foreground和background,所以cls=2k scores;而每個(gè)anchor都有[x, y, w, h]對(duì)應(yīng)4個(gè)偏移量,所以reg=4k coordinates
  • 補(bǔ)充一點(diǎn),這k個(gè)anchor全部拿去訓(xùn)練太多了,訓(xùn)練程序會(huì)隨機(jī)選取k中256個(gè)合適的anchors進(jìn)行訓(xùn)練,這個(gè)256與上面的256-d不同(什么是合適的anchors下文5.1有解釋)
  • 注意,在本文講解中使用的VGG conv5 num_output=512,所以是512d,其他類似.....

    2.3 softmax判定foreground與background

    ?

    縮進(jìn)一副MxN大小的矩陣送入Faster RCNN網(wǎng)絡(luò)后,到RPN網(wǎng)絡(luò)變?yōu)?M/16)x(N/16),不妨設(shè)W=M/16,H=N/16。在進(jìn)入reshape與softmax之前,先做了1x1卷積,如圖8: 圖8 RPN中判定fg/bg網(wǎng)絡(luò)結(jié)構(gòu) 該1x1卷積的caffe prototxt定義如下: [cpp]?view plaincopy
  • layer?{??
  • ??name:?"rpn_cls_score"??
  • ??type:?"Convolution"??
  • ??bottom:?"rpn/output"??
  • ??top:?"rpn_cls_score"??
  • ??convolution_param?{??
  • ????num_output:?18???#?2(bg/fg)?*?9(anchors)??
  • ????kernel_size:?1?pad:?0?stride:?1??
  • ??}??
  • }??
  • 可以看到其num_output=18,也就是經(jīng)過該卷積的輸出圖像為WxHx18大小(注意第二章開頭提到的卷積計(jì)算方式)。這也就剛好對(duì)應(yīng)了feature maps每一個(gè)點(diǎn)都有9個(gè)anchors,同時(shí)每個(gè)anchors又有可能是foreground和background,所有這些信息都保存WxHx(9x2)大小的矩陣。為何這樣做?后面接softmax分類獲得foreground anchors,也就相當(dāng)于初步提取了檢測(cè)目標(biāo)候選區(qū)域box(一般認(rèn)為目標(biāo)在foreground anchors中)。 縮進(jìn)那么為何要在softmax前后都接一個(gè)reshape layer?其實(shí)只是為了便于softmax分類,至于具體原因這就要從caffe的實(shí)現(xiàn)形式說起了。在caffe基本數(shù)據(jù)結(jié)構(gòu)blob中以如下形式保存數(shù)據(jù): blob=[batch_size, channel,height,width] 對(duì)應(yīng)至上面的保存bg/fg anchors的矩陣,其在caffe blob中的存儲(chǔ)形式為[1, 2*9, H, W]。而在softmax分類時(shí)需要進(jìn)行fg/bg二分類,所以reshape layer會(huì)將其變?yōu)閇1, 2, 9*H, W]大小,即單獨(dú)“騰空”出來一個(gè)維度以便softmax分類,之后再reshape回復(fù)原狀。貼一段caffe softmax_loss_layer.cpp的reshape函數(shù)的解釋,非常精辟: [cpp]?view plaincopy
  • "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)絡(luò)中利用anchors和softmax初步提取出foreground anchors作為候選區(qū)域。

    ?

    2.4 bounding box regression原理

    ?

    縮進(jìn)介紹bounding box regression數(shù)學(xué)模型及原理。如圖9所示綠色框?yàn)轱w機(jī)的Ground Truth(GT),紅色為提取的foreground anchors,那么即便紅色的框被分類器識(shí)別為飛機(jī),但是由于紅色的框定位不準(zhǔn),這張圖相當(dāng)于沒有正確的檢測(cè)出飛機(jī)。所以我們希望采用一種方法對(duì)紅色的框進(jìn)行微調(diào),使得foreground anchors和GT更加接近。

    ?

    圖9

    縮進(jìn)對(duì)于窗口一般使用四維向量(x, y, w, h)表示,分別表示窗口的中心點(diǎn)坐標(biāo)和寬高。對(duì)于圖 10,紅色的框A代表原始的Foreground Anchors,綠色的框G代表目標(biāo)的GT,我們的目標(biāo)是尋找一種關(guān)系,使得輸入原始的anchor A經(jīng)過映射得到一個(gè)跟真實(shí)窗口G更接近的回歸窗口G',即:給定A=(Ax, Ay, Aw, Ah),尋找一種映射f,使得f(Ax, Ay, Aw, Ah)=(G'x, G'y, G'w, G'h),其中(G'x, G'y, G'w, G'h)≈(Gx, Gy, Gw, Gh)。

    圖10

    那么經(jīng)過何種變換才能從圖6中的A變?yōu)镚'呢? 比較簡(jiǎn)單的思路就是:

    縮進(jìn)?1. 先做平移

    縮進(jìn)?2. 再做縮放

    縮進(jìn)觀察上面4個(gè)公式發(fā)現(xiàn),需要學(xué)習(xí)的是dx(A),dy(A),dw(A),dh(A)這四個(gè)變換。當(dāng)輸入的anchor與GT相差較小時(shí),可以認(rèn)為這種變換是一種線性變換, 那么就可以用線性回歸來建模對(duì)窗口進(jìn)行微調(diào)(注意,只有當(dāng)anchors和GT比較接近時(shí),才能使用線性回歸模型,否則就是復(fù)雜的非線性問題了)。對(duì)應(yīng)于Faster RCNN原文,平移量(tx, ty)與尺度因子(tw, th)如下:

    縮進(jìn)接下來的問題就是如何通過線性回歸獲得dx(A),dy(A),dw(A),dh(A)了。線性回歸就是給定輸入的特征向量X, 學(xué)習(xí)一組參數(shù)W, 使得經(jīng)過線性回歸后的值跟真實(shí)值Y(即GT)非常接近,即Y=WX。對(duì)于該問題,輸入X是一張經(jīng)過num_output=1的1x1卷積獲得的feature map,定義為Φ;同時(shí)還有訓(xùn)練傳入的GT,即(tx,?ty, tw, th)。輸出是dx(A),dy(A),dw(A),dh(A)四個(gè)變換。那么目標(biāo)函數(shù)可以表示為:

    其中Φ(A)是對(duì)應(yīng)anchor的feature map組成的特征向量,w是需要學(xué)習(xí)的參數(shù),d(A)是得到的預(yù)測(cè)值(*表示 x,y,w,h,也就是每一個(gè)變換對(duì)應(yīng)一個(gè)上述目標(biāo)函數(shù))。為了讓預(yù)測(cè)值(tx, ty,?tw,?th)與真實(shí)值最小,得到損失函數(shù):

    函數(shù)優(yōu)化目標(biāo)為:

    2.5 對(duì)proposals進(jìn)行bounding box regression

    縮進(jìn)在了解bounding box regression后,再回頭來看RPN網(wǎng)絡(luò)第二條線路,如圖11。

    ?

    圖11 RPN中的bbox reg

    先來看一看上圖11中1x1卷積的caffe prototxt定義:

    [cpp]?view plaincopy
  • 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存儲(chǔ)為[1, 36, H, W]。與上文中fg/bg anchors存儲(chǔ)為[1, 18, H, W]類似,這里相當(dāng)于feature maps每個(gè)點(diǎn)都有9個(gè)anchors,每個(gè)anchors又都有4個(gè)用于回歸的[dx(A),dy(A),dw(A),dh(A)]變換量。利用上面的的計(jì)算公式即可從foreground anchors回歸出proposals。

    2.6 Proposal Layer

    ?

    縮進(jìn)Proposal Layer負(fù)責(zé)綜合所有[dx(A),dy(A),dw(A),dh(A)]變換量和foreground anchors,計(jì)算出精準(zhǔn)的proposal,送入后續(xù)RoI Pooling Layer。還是先來看看Proposal Layer的caffe prototxt定義: [cpp]?view plaincopy
  • 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個(gè)輸入:fg/bg anchors分類器結(jié)果rpn_cls_prob_reshape,對(duì)應(yīng)的bbox reg的[dx(A),dy(A),dw(A),dh(A)]變換量rpn_bbox_pred,以及im_info;另外還有參數(shù)feat_stride=16,這和圖4是對(duì)應(yīng)的。 縮進(jìn)首先解釋im_info。對(duì)于一副任意大小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則保存了該信息。所有這些數(shù)值都是為了將proposal映射回原圖而設(shè)置的,如圖12,畢竟檢測(cè)就是為了在原圖上畫一個(gè)框而已~ 圖12 縮進(jìn)Proposal Layer forward(caffe layer的前傳函數(shù))按照以下順序依次處理:
  • 再次生成anchors,并對(duì)所有的anchors做bbox reg位置回歸(注意這里的anchors生成順序和之前是即完全一致的)
  • 按照輸入的foreground softmax scores由大到小排序anchors,提取前pre_nms_topN(e.g. 6000)個(gè)anchors。即提取修正位置后的foreground anchors
  • 利用feat_stride和im_info將anchors映射回原圖,判斷fg anchors是否大范圍超過邊界,剔除嚴(yán)重超出邊界fg anchors。
  • 進(jìn)行nms(nonmaximum suppression,非極大值抑制)
  • 再次按照nms后的foreground softmax scores由大到小排序fg anchors,提取前post_nms_topN(e.g. 300)結(jié)果作為proposal輸出。
  • 之后輸出proposal=[x1, y1, x2, y2],注意,由于在第三步中將anchors映射回原圖判斷是否超出邊界,所以這里輸出的proposal是對(duì)應(yīng)MxN輸入圖像尺度的,這點(diǎn)在后續(xù)網(wǎng)絡(luò)中有用。另外我認(rèn)為,嚴(yán)格意義上的檢測(cè)應(yīng)該到此就結(jié)束了,后續(xù)部分應(yīng)該屬于識(shí)別了~ RPN網(wǎng)絡(luò)結(jié)構(gòu)就介紹到這里,總結(jié)起來就是: 生成anchors -> softmax分類器提取fg anchors?-> bbox reg回歸fg anchors -> Proposal Layer生成proposals

    ?

    3 RoI pooling

    縮進(jìn)而RoI Pooling層則負(fù)責(zé)收集proposal,并計(jì)算出proposal feature maps,送入后續(xù)網(wǎng)絡(luò)。從圖3中可以看到Rol pooling層有2個(gè)輸入:

  • 原始的feature maps
  • RPN輸出的proposal boxes(大小各不相同)
  • 3.1 為何需要RoI Pooling

    縮進(jìn)先來看一個(gè)問題:對(duì)于傳統(tǒng)的CNN(如AlexNet,VGG),當(dāng)網(wǎng)絡(luò)訓(xùn)練好后輸入的圖像尺寸必須是固定值,同時(shí)網(wǎng)絡(luò)輸出也是固定大小的vector or matrix。如果輸入圖像大小不定,這個(gè)問題就變得比較麻煩。有2種解決辦法:

  • 從圖像中crop一部分傳入網(wǎng)絡(luò)
  • 將圖像warp成需要的大小后傳入網(wǎng)絡(luò)
  • 圖13 crop與warp破壞圖像原有結(jié)構(gòu)信息

    兩種辦法的示意圖如圖13,可以看到無論采取那種辦法都不好,要么crop后破壞了圖像的完整結(jié)構(gòu),要么warp破壞了圖像原始形狀信息。回憶RPN網(wǎng)絡(luò)生成的proposals的方法:對(duì)foreground anchors進(jìn)行bound box regression,那么這樣獲得的proposals也是大小形狀各不相同,即也存在上述問題。所以Faster RCNN中提出了RoI Pooling解決這個(gè)問題(需要說明,RoI Pooling確實(shí)是從SPP發(fā)展而來,但是限于篇幅這里略去不講,有興趣的讀者可以自行查閱相關(guān)論文)。

    3.2 RoI Pooling原理

    縮進(jìn)分析之前先來看看RoI Pooling Layer的caffe prototxt的定義:

    ?

    [cpp]?view plaincopy
  • 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=7,另外一個(gè)參數(shù)spatial_scale=1/16應(yīng)該能夠猜出大概吧。

    縮進(jìn)RoI Pooling layer forward過程:在之前有明確提到:proposal=[x1, y1, x2, y2]是對(duì)應(yīng)MxN尺度的,所以首先使用spatial_scale參數(shù)將其映射回MxN大小的feature maps尺度(這里來回多次映射,是有點(diǎn)繞);之后將每個(gè)proposal水平和豎直都分為7份,對(duì)每一份都進(jìn)行max pooling處理。這樣處理后,即使大小不同的proposal,輸出結(jié)果都是7x7大小,實(shí)現(xiàn)了fixed-length output。

    ?

    圖14 proposal示意圖

    ?

    4 Classification

    縮進(jìn)Classification部分利用已經(jīng)獲得的proposal feature maps,通過full connect層與softmax計(jì)算每個(gè)proposal具體屬于那個(gè)類別(如人,車,電視等),輸出cls_prob概率向量;同時(shí)再次利用bounding box regression獲得每個(gè)proposal的位置偏移量bbox_pred,用于回歸更加精確的目標(biāo)檢測(cè)框。Classification部分網(wǎng)絡(luò)結(jié)構(gòu)如圖15。 圖15?Classification部分網(wǎng)絡(luò)結(jié)構(gòu)圖

    從PoI Pooling獲取到7x7=49大小的proposal feature maps后,送入后續(xù)網(wǎng)絡(luò),可以看到做了如下2件事:

  • 通過全連接和softmax對(duì)proposals進(jìn)行分類,這實(shí)際上已經(jīng)是識(shí)別的范疇了
  • 再次對(duì)proposals進(jìn)行bounding box regression,獲取更高精度的rect box
  • 這里來看看全連接層InnerProduct layer,如圖16,

    圖16 全連接層示意圖

    其計(jì)算公式如下:

    其中W和bias B都是預(yù)先訓(xùn)練好的,即大小是固定的,當(dāng)然輸入X和輸出Y也就是固定大小。所以,這也就印證了之前Poi Pooling的必要性。到這里,我想其他內(nèi)容已經(jīng)很容易理解,不在贅述了。

    5 Faster RCNN訓(xùn)練

    縮進(jìn)Faster CNN的訓(xùn)練,是在已經(jīng)訓(xùn)練好的model(如VGG_CNN_M_1024,VGG,ZF)的基礎(chǔ)上繼續(xù)進(jìn)行訓(xùn)練。實(shí)際中訓(xùn)練過程分為6個(gè)步驟:
  • 在已經(jīng)訓(xùn)練好的model上,訓(xùn)練RPN網(wǎng)絡(luò),對(duì)應(yīng)stage1_rpn_train.pt
  • 利用步驟1中訓(xùn)練好的RPN網(wǎng)絡(luò),收集proposals,對(duì)應(yīng)rpn_test.pt
  • 第一次訓(xùn)練Fast RCNN網(wǎng)絡(luò),對(duì)應(yīng)stage1_fast_rcnn_train.pt
  • 第二訓(xùn)練RPN網(wǎng)絡(luò),對(duì)應(yīng)stage2_rpn_train.pt
  • 再次利用步驟4中訓(xùn)練好的RPN網(wǎng)絡(luò),收集proposals,對(duì)應(yīng)rpn_test.pt
  • 第二次訓(xùn)練Fast RCNN網(wǎng)絡(luò),對(duì)應(yīng)stage2_fast_rcnn_train.pt
  • 可以看到訓(xùn)練過程類似于一種“迭代”的過程,不過只循環(huán)了2次。至于只循環(huán)了2次的原因是應(yīng)為作者提到:"A similar alternating training can be run for more iterations, but we have observed negligible improvements",即循環(huán)更多次沒有提升了。接下來本章以上述6個(gè)步驟講解訓(xùn)練過程。

    5.1 訓(xùn)練RPN網(wǎng)絡(luò)

    縮進(jìn)在該步驟中,首先讀取RBG提供的預(yù)訓(xùn)練好的model(本文使用VGG),開始迭代訓(xùn)練。來看看stage1_rpn_train.pt網(wǎng)絡(luò)結(jié)構(gòu),如圖17。

    圖17 stage1_rpn_train.pt

    (考慮圖片大小,Conv Layers中所有的層都畫在一起了,如紅圈所示,后續(xù)圖都如此處理)

    與檢測(cè)網(wǎng)絡(luò)類似的是,依然使用Conv Layers提取feature maps。整個(gè)網(wǎng)絡(luò)使用的Loss如下:

    上述公式中,i表示anchors index,pi表示foreground softmax?predict概率,pi*代表對(duì)應(yīng)的GT predict概率(即當(dāng)?shù)趇個(gè)anchor與GT間IoU>0.7,認(rèn)為是該anchor是foreground,pi*=1;反之IoU<0.3時(shí),認(rèn)為是該anchor是background,pi*=0;至于那些0.3<IoU<0.7的anchor則不參與訓(xùn)練);t代表predict bounding box,t*代表對(duì)應(yīng)foreground anchor對(duì)應(yīng)的GT box。可以看到,整個(gè)Loss分為2部分:

  • cls loss,即rpn_cls_loss層計(jì)算的softmax loss,用于分類anchors為forground與background的網(wǎng)絡(luò)訓(xùn)練
  • reg loss,即rpn_loss_bbox層計(jì)算的soomth L1 loss,用于bounding box regression網(wǎng)絡(luò)訓(xùn)練。注意在該loss中乘了pi*,相當(dāng)于只關(guān)心foreground anchors的回歸(其實(shí)在回歸中也完全沒必要去關(guān)心background)。
  • 縮進(jìn)由于在實(shí)際過程中,Ncls和Nreg差距過大,用參數(shù)λ平衡二者(如Ncls=256,Nreg=2400時(shí)設(shè)置λ=10),使總的網(wǎng)絡(luò)Loss計(jì)算過程中能夠均勻考慮2種Loss。這里比較重要是Lreg使用的soomth L1 loss,計(jì)算公式如下:

    縮進(jìn)了解數(shù)學(xué)原理后,反過來看圖17:

  • 對(duì)于rpn_loss_cls,輸入的rpn_cls_scors_reshape和rpn_labels分別對(duì)應(yīng)p與p*,Ncls參數(shù)隱含在p與p*的blob的大小中
  • 對(duì)于rpn_loss_bbox,輸入的rpn_bbox_pred和rpn_bbox_targets分別對(duì)應(yīng)t于t*,rpn_bbox_inside_weigths對(duì)應(yīng)p*,rpn_bbox_outside_weights對(duì)應(yīng)λ,Nreg同樣隱含在blob大小中
  • 這樣,公式與代碼就完全對(duì)應(yīng)了。

    5.2 通過訓(xùn)練好的RPN網(wǎng)絡(luò)收集proposals

    ?

    縮進(jìn)在該步驟中,利用之前的RPN網(wǎng)絡(luò),獲取proposal rois,同時(shí)獲取foreground softmax probability,如圖18,然后將獲取的信息保存在python pickle文件中。該網(wǎng)絡(luò)本質(zhì)上和檢測(cè)中的RPN網(wǎng)絡(luò)一樣,沒有什么區(qū)別。

    圖18 rpn_test.pt

    5.3 訓(xùn)練Fast RCNN網(wǎng)絡(luò)

    ?

    縮進(jìn)讀取之前保存的pickle文件,獲取proposals與foreground?probability。從data層輸入網(wǎng)絡(luò)。然后:

  • 將提取的proposals作為rois傳入網(wǎng)絡(luò),如圖19藍(lán)框
  • 將foreground?probability作為bbox_inside_weights傳入網(wǎng)絡(luò),如圖19綠框
  • 通過caffe blob大小對(duì)比,計(jì)算出bbox_outside_weights(即λ),如圖19綠框
  • 這樣就可以訓(xùn)練最后的識(shí)別softmax與最終的bounding regression了,如圖19。

    圖19 stage1_fast_rcnn_train.pt

    之后的訓(xùn)練都是大同小異,不再贅述了。

    ?

    RPN網(wǎng)絡(luò):

    name: 'input-data' #這一層就是最開始數(shù)據(jù)輸入type: 'Python'top: 'data' # top表示該層的輸出,所以可以看到這一層輸出三組數(shù)據(jù),data,真值框gt_boxes,和相關(guān)信息im_infotop: 'im_info' # 這些都是存儲(chǔ)在矩陣中的top: 'gt_boxes'python_param {module: 'roi_data_layer.layer'layer: 'RoIDataLayer'param_str: "'num_classes': 21"} }#========= conv1-conv5 ============layer {name: "conv1"type: "Convolution"bottom: "data" # 輸入datatop: "conv1" # 輸出conv1,這里conv1就代表了這一層輸出數(shù)據(jù)的名稱,存儲(chǔ)在對(duì)應(yīng)的矩陣中param { lr_mult: 1.0 }param { lr_mult: 2.0 }convolution_param {num_output: 96kernel_size: 7pad: 3 # 這里可以看到卷積1層 填充了3個(gè)像素stride: 2} } layer {name: "relu1"type: "ReLU"bottom: "conv1"top: "conv1" } layer {name: "norm1"type: "LRN"bottom: "conv1"top: "norm1" # 做歸一化操作,通俗點(diǎn)說就是做個(gè)除法lrn_param {local_size: 3alpha: 0.00005beta: 0.75norm_region: WITHIN_CHANNELengine: CAFFE} } layer {name: "pool1"type: "Pooling"bottom: "norm1"top: "pool1"pooling_param {kernel_size: 3stride: 2pad: 1 # 池化的時(shí)候,又做了填充pool: MAX} } layer {name: "conv2"type: "Convolution"bottom: "pool1"top: "conv2"param { lr_mult: 1.0 }param { lr_mult: 2.0 }convolution_param {num_output: 256kernel_size: 5pad: 2stride: 2} } layer {name: "relu2"type: "ReLU"bottom: "conv2"top: "conv2" } layer {name: "norm2"type: "LRN"bottom: "conv2"top: "norm2"lrn_param {local_size: 3alpha: 0.00005beta: 0.75norm_region: WITHIN_CHANNELengine: CAFFE} } layer {name: "pool2"type: "Pooling"bottom: "norm2"top: "pool2"pooling_param {kernel_size: 3stride: 2pad: 1pool: MAX} } layer {name: "conv3"type: "Convolution"bottom: "pool2"top: "conv3"param { lr_mult: 1.0 }param { lr_mult: 2.0 }convolution_param {num_output: 384kernel_size: 3pad: 1stride: 1} } layer {name: "relu3"type: "ReLU"bottom: "conv3"top: "conv3" } layer {name: "conv4"type: "Convolution"bottom: "conv3"top: "conv4"param { lr_mult: 1.0 }param { lr_mult: 2.0 }convolution_param {num_output: 384kernel_size: 3pad: 1stride: 1} } layer {name: "relu4"type: "ReLU"bottom: "conv4"top: "conv4" } layer {name: "conv5"type: "Convolution"bottom: "conv4"top: "conv5"param { lr_mult: 1.0 }param { lr_mult: 2.0 }convolution_param {num_output: 256kernel_size: 3pad: 1stride: 1} } layer {name: "relu5"type: "ReLU"bottom: "conv5"top: "conv5" }#========= RPN ============ # 到我們的RPN網(wǎng)絡(luò)部分了,前面的都是共享的5層卷積層的部分 layer {name: "rpn_conv1"type: "Convolution"bottom: "conv5"top: "rpn_conv1"param { lr_mult: 1.0 }param { lr_mult: 2.0 }convolution_param {num_output: 256kernel_size: 3 pad: 1 stride: 1 #這里作者把每個(gè)滑窗3*3,通過3*3*256*256的卷積核輸出256維,完整的輸出其實(shí)是12*12*256,weight_filler { type: "gaussian" std: 0.01 }bias_filler { type: "constant" value: 0 }} } layer {name: "rpn_relu1"type: "ReLU"bottom: "rpn_conv1"top: "rpn_conv1" } layer {name: "rpn_cls_score"type: "Convolution"bottom: "rpn_conv1"top: "rpn_cls_score"param { lr_mult: 1.0 }param { lr_mult: 2.0 }convolution_param {num_output: 18 # 2(bg/fg) * 9(anchors)kernel_size: 1 pad: 0 stride: 1 #這里看的很清楚,作者通過1*1*256*18的卷積核,將前面的256維數(shù)據(jù)轉(zhuǎn)換成了18個(gè)輸出weight_filler { type: "gaussian" std: 0.01 }bias_filler { type: "constant" value: 0 }} } layer {name: "rpn_bbox_pred"type: "Convolution"bottom: "rpn_conv1"top: "rpn_bbox_pred"param { lr_mult: 1.0 }param { lr_mult: 2.0 }convolution_param {num_output: 36 # 4 * 9(anchors)kernel_size: 1 pad: 0 stride: 1 <span style="font-family: Arial, Helvetica, sans-serif;">#這里看的很清楚,作者通過1*1*256*36的卷積核,將前面的256維數(shù)據(jù)轉(zhuǎn)換成了36個(gè)輸出</span>weight_filler { type: "gaussian" std: 0.01 }bias_filler { type: "constant" value: 0 }} } layer {bottom: "rpn_cls_score"top: "rpn_cls_score_reshape" # 我們之前說過,其實(shí)這一層是12*12*256的,所以后面我們要送給損失函數(shù),需要將這個(gè)矩陣reshape一下,我們需要的是144個(gè)滑窗,每個(gè)對(duì)應(yīng)的256的向量name: "rpn_cls_score_reshape"type: "Reshape"reshape_param { shape { dim: 0 dim: 2 dim: -1 dim: 0 } } } layer {name: 'rpn-data'type: 'Python'bottom: 'rpn_cls_score'bottom: 'gt_boxes'bottom: 'im_info'bottom: 'data'top: 'rpn_labels'top: 'rpn_bbox_targets'top: 'rpn_bbox_inside_weights'top: 'rpn_bbox_outside_weights'python_param {module: 'rpn.anchor_target_layer'layer: 'AnchorTargetLayer'param_str: "'feat_stride': 16"} } layer {name: "rpn_loss_cls"type: "SoftmaxWithLoss" # 很明顯這里是計(jì)算softmax的損失,輸入labels和cls layer的18個(gè)輸出(中間reshape了一下),輸出損失函數(shù)的具體值bottom: "rpn_cls_score_reshape"bottom: "rpn_labels"propagate_down: 1propagate_down: 0top: "rpn_cls_loss"loss_weight: 1loss_param {ignore_label: -1normalize: true} } layer {name: "rpn_loss_bbox"type: "SmoothL1Loss" # 這里計(jì)算的框回歸損失函數(shù)具體的值bottom: "rpn_bbox_pred"bottom: "rpn_bbox_targets"bottom: "rpn_bbox_inside_weights"bottom: "rpn_bbox_outside_weights"top: "rpn_loss_bbox"loss_weight: 1smooth_l1_loss_param { sigma: 3.0 } }#========= RCNN ============ # Dummy layers so that initial parameters are saved into the output netlayer {name: "dummy_roi_pool_conv5"type: "DummyData"top: "dummy_roi_pool_conv5"dummy_data_param {shape { dim: 1 dim: 9216 }data_filler { type: "gaussian" std: 0.01 }} } layer {name: "fc6"type: "InnerProduct"bottom: "dummy_roi_pool_conv5"top: "fc6"param { lr_mult: 0 decay_mult: 0 }param { lr_mult: 0 decay_mult: 0 }inner_product_param {num_output: 4096} } layer {name: "relu6"type: "ReLU"bottom: "fc6"top: "fc6" } layer {name: "fc7"type: "InnerProduct"bottom: "fc6"top: "fc7"param { lr_mult: 0 decay_mult: 0 }param { lr_mult: 0 decay_mult: 0 }inner_product_param {num_output: 4096} } layer {name: "silence_fc7"type: "Silence"bottom: "fc7"

      

    對(duì)于每個(gè)3x3的窗口,作者就計(jì)算這個(gè)滑動(dòng)窗口的中心點(diǎn)所對(duì)應(yīng)的原始圖片的中心點(diǎn)。然后作者假定,這個(gè)3x3窗口,是從原始圖片上通過SPP池化得到的,而這個(gè)池化的區(qū)域的面積以及比例,就是一個(gè)個(gè)的anchor。換句話說,對(duì)于每個(gè)3x3窗口,作者假定它來自9種不同原始區(qū)域的池化,但是這些池化在原始圖片中的中心點(diǎn),都完全一樣。這個(gè)中心點(diǎn),就是剛才提到的,3x3窗口中心點(diǎn)所對(duì)應(yīng)的原始圖片中的中心點(diǎn)。如此一來,在每個(gè)窗口位置,我們都可以根據(jù)9個(gè)不同長(zhǎng)寬比例、不同面積的anchor,逆向推導(dǎo)出它所對(duì)應(yīng)的原始圖片中的一個(gè)區(qū)域,這個(gè)區(qū)域的尺寸以及坐標(biāo),都是已知的。而這個(gè)區(qū)域,就是我們想要的 proposal。所以我們通過滑動(dòng)窗口和anchor,成功得到了 51x39x9 個(gè)原始圖片的proposal。接下來,每個(gè)proposal我們只輸出6個(gè)參數(shù):每個(gè) proposal 和 ground truth 進(jìn)行比較得到的前景概率和背景概率(2個(gè)參數(shù))(對(duì)應(yīng)圖上的 cls_score);由于每個(gè) proposal 和 ground truth 位置及尺寸上的差異,從 proposal 通過平移放縮得到 ground truth 需要的4個(gè)平移放縮參數(shù)(對(duì)應(yīng)圖上的 bbox_pred)。

    所以根據(jù)我們剛才的計(jì)算,我們一共得到了多少個(gè)anchor box呢?

    51 x 39 x 9 = 17900

    約等于 20 k

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/wuxiangli/p/7066707.html

    總結(jié)

    以上是生活随笔為你收集整理的rcnn -fast rcnn-faster rcnn物体检测论文的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。