Mask RCNN 源碼閱讀(update)


 

         之前看了Google官網的object_dectect 的源碼,感覺Google大神寫的還不錯。最近想玩下Mask RCNN,就看了下源碼,這里剛好當做總結和梳理。鏈接如下:

Google官網的object_dectect:https://github.com/tensorflow/models/tree/master/research/object_detection

Mask RCNN: https://github.com/matterport/Mask_RCNN

一個使用tensorflow 寫的,一個是用keras寫的,我自己是對tensorflow 會熟悉,但是kearas沒用過,不過不影響看代碼哈。有個比較困惑的地方,

好像我記得faster rcnn 中的rpn網絡first stage的loss是proposals 和 gt_box的loss,而mask rcnn 是調出來進入第二步驟的正樣本的proposals 和對應gt_box的loss,

雖然實際training中可能結果是一樣的(我們一般會設置一個比較大的值,使得圖像中所有的正樣本都被框中,且進入second stage training).恩,廢話不多說,開始

寫mask rcnn 的源碼閱讀理解啦。這里簡單的梳理下數據流向,就是圖像被處理的一個個步驟,不過得對faster rcnn 和 fpn兩個網絡有所了解才好。

(一般閱讀代碼,使用py的文件比較多,進入函數,單步調試之類的,mask rcnn的例子都是ipynb,一般調成.py,在pycharm上單步調試。)

 

 

簡而言之,mask rcnn 使用的是faster rcnn 的框架,和使用fpn的網絡提取特征,在這個基礎上增加了mask的預測。

事前准備:

訓練數據 image

 

數據label:關於image的目標分割圖

label的特征是對目標可以分割出來

 

然后,處理流程是這樣的:

輸入一張圖,然后進入使用fpn網絡提取特征,基本特征網絡結構是resnet,框架是fpn的金字塔結構,如下圖:

 

 簡要介紹是:

1-卷積過程:

一張圖進入,resnet 不是有4個block,每個block提取的特征輸出保存住,構成list [ c2,c3,c4,c5],代碼如下:

 

2-上采樣過程

 將頂端的c5進行上采樣,生成list [p2,p3,p4,p5,p6],其中p6是通過p5,加一次池化polling得到的。代碼如下:

得到以后,first stage 和second stage的公共部分就得到啦,現在要分別處理了哦:

然后,就是兩個過程,一個是 rpn過程,一個是mrcnn過程

 1-rnp過程:

        rpn做啥???全稱是Region Proposal Network,就是生成目標的矩形塊,在faster rcnn中,只有一個feature map最終

的輸出作為rpn的輸入,就是 一個feature map 加上幾層卷積,fully connect network ,然后就輸出了rpn_bbox,rpn_prob,rpn_logit,

代碼如下,輸入的 x就是feature map

 

然而!!!,fpn網絡是有多個 feature map 作為支撐輸出 rpn的,所有作者這里就 把rpn網絡包裝成一個model,然后,

rpn_feature_map 中有的p2,p3,p4,p5,p6,一個個輸入,再一個個輸出,就可以的得到不同尺度的proposals box:

包裝成model:

一個個提取proposals box:

這時候我們肯定會有疑問啦,不同尺寸的bbox可以放在一起嗎?答案是可以的,因為,他們是歸一化以后的,就像1/2 =2/4,一個樣子。

接下來怎么辦?,rpn還沒有結束,rpn要變成roi,就是生成的框還要挑選下,變成生成的框+感興趣的框(interest),所以要進入nms:

這里有幾點要注意,就是rpn網絡預測的實際上不是 object bbox,而是基於anchor的deata,就是圖片中本來就有bbox(anchor),rpn預測的只是

這些anchor 離object 的bbox的中心偏差多少,長寬比偏差多少?示意圖如下:

   

 

這里的rpn講的不錯:http://www.cnblogs.com/dudumiaomiao/p/6560841.html    

 

    到此,first stage 基本結束,其實first stage做的是將目標找出來(不管目標是哪一個類別),接下來就是生成first stage rpn 和 anchor 一起生成bbox的過程(在Google object detection 代碼中

這個過程叫做解碼,把bbox信息解碼出來):

自此,first stage 暫時到這里,就是輸出了 bbox proposals ,object_classifier_prob,(目的是是否目標)

2-mrcnn過程:

對於DEtectionTargetLayer 這個函數對於:功能是

1、通過first stage 生成的proposals 和gt_box計算出iou矩陣 ,並通過iou值,取(crop)出正樣本的feature map 和負樣本的\feature map (

為什么這么搞,因為后期訓練需要正負樣本才能訓練,如果全是正樣本那就模型失效啦,為什么coco數據集是默認0.33正樣本,因為其實我們

經常識別的目標在場景中都是占的比例是較少的,所以這里訓練時給個經驗值讓正樣本偏少些,但是正負樣本比例不能差距太大,不然就訓練

不收斂,假如0.1,則不訓練隨機猜測為負樣本的准確率都有90%),其中正負樣本比例通過config.ROI_POSITIVE_RATIO設置。

代碼如下:

 

同時通過proposals和gt_box的偏差獲得mask的偏差

這里大家可能有疑問:不是得用image height和width嗎?為什么這里分母是:gt_h,gt_w,且mask又是怎樣的一個形式。在config中有一個

配置項:config.USE_MINI_MASK,這個配置項目默認值是True,目的是為了在存儲使用mask的時候使用小mask,也就是以object的bbox

為height和width(這樣多余的0就不需要存儲了)。所以就有了上面的gt_h,gt_w,當時看到這里的時候在想,不是得用image height和width

嗎?后面看到 if config.USE_MINI_MASK就明白啦。

 這里再多說兩句,關於mask又是怎樣的一個形式

我們使用load_mask()函數,輸出的是一個個和圖像一樣大小的mask,且該圖像中有多少個目標,就mask就有多少個channal,一個目標

一個channal,用以后期提取bbox方便。然后,config.USE_MINI_MASK = True,就會再配置

這樣,一張和圖片同樣大小的mask輸入后,先將目標的bbox提取出來,再從大圖片中crop出目標,然后在resize到(56*56),這樣就節省

內存啦。

至此,准備工作做好了,接下來就是要求出每個proposals的類別(是人,還是自行車。。。。),並refine bbox和預測mask.

接下來講兩個函數,一個是fpn_classifier_graph,一個是build_fpn_mask_graph。前面的是對proposals中預測類別,后面的是預測mask,輸入的都是

mrcnn_featur_map.

2、通過fpn_classifier_graph,

 

(更新)這里有個挺有趣的,就是,我們得到proposals后,要獲得目標的feature map 信息,但是

我們的特征是 金字塔的(pyramid)的,從哪個圖層crop下來呢?這里就有一個根據你的框的大小定位到一個圖層的計算公式:

具體公式看fpn 那篇論文,表達的是框越小,level 越小,(目標小,level低的圖層保留信息較完善,所以crop  level低的圖層)

 

 

 

目標識別的傳統操作,輸出logits,probs,bbox。

 

2、通過buil_fpn_mask_grph,都是傳統操作,卷積、fully connect,輸出想要的結果:

至此,程序就差不多結束啦,后面就是loss了:

 (更新)對於loss的簡要介紹:

rpn_class_loss_graph:是 在rpn階段識別的前景/背景的loss計算,這種分類的一般是交叉熵loss,見下:

:這個是rpn bbox loss,有一個trick 就是,這里只統計偏差(diff,見下面代碼)比例小於1的,因為大於1的沒有必要

就像faster rcnn選擇iou > 0.7,為正樣本,小於0.3的為負樣本,當偏差大於1的時候,距離太遠了,iou肯定是小的,這種loss不計算在內:

:同樣的,對於類別分類使用交叉熵,這里就不給出了。

:使用l1 loss 為什么和上面不一樣呢?實際和rpn bbox 差不多,就是取差值

:使用的是binary 交叉熵,做損失統計,我記得之前傳統的分割方法,比如(

FC-DenseNet56)等,使用的loss是cross_entropy 有,還有一種是lovasz

 

Q/A(更新):

   1、mask cnn引入預測K個輸出的機制,允許每個類都生成獨立的掩膜,避免類間競爭。這樣做解耦了掩膜和種類預測,這句話的理解?

嗯,其實就是對於一個目標(或proposal)都生成number_classes 的mask,然后,只有與預測相一致類別的mask才會對loss有貢獻,

並且,使用binary cross-entropy loss (具體是tf.nn.sigmoid_cross_entropy_with_logits)進行訓練,這和傳統的圖像分割不一樣,傳統的圖像經過fcn網絡在像素級上分割,每個像素進行分類,這樣就會導致類間的區域競爭,最后識別分割的結果出現顆粒感比較重的感覺,fcn使用的loss計算是SoftmaxLoss(具體是:tf.nn.softmax_cross_entropy_with_logits)。其實,binary cross-entropy loss常用在2分類,SoftmaxLoss是在多分類的,基本計算loss的原理都差不多,都是和ground truth的差(或“距離”)。

 

 

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

最最后面放一下我的筆記,按我的建議是不建議大家看的,主要目的是筆記本的筆記容易丟,放在網上看的時候方便,給我自己看的哈(字漂,一般人都看不懂!)

 

 

 

 

 

 


免責聲明!

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



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