MaskRCNN網絡結構
MaskRCNN作為FasterRCNN的擴展,產生RoI的RPN網絡和FasterRCNN網絡。
結構:ResNet101+FPN
代碼:TensorFlow+ Keras(Python)
代碼中將Resnet101網絡,分成5個stage,記為[C1,C2,C3,C4,C5];這里的5個階段分別對應着5中不同尺度的feature map輸出,用來建立FPN網絡的特征金字塔(feature pyramid).
先通過兩張MaskRCNN整體網絡結構圖,再附帶一張繪制了stage1和stage2的層次結構圖(stage3到stage5的結構層次比較多,未繪制),整體了解下MaskRCNN網絡。
MaskRCNN網絡結構泛化圖:
MaskRCNN網絡結構細化圖:
stage1和stage2層次結構圖:
Mask-RCNN 技術要點
● 技術要點1 - 強化的基礎網絡
通過 ResNeXt-101+FPN 用作特征提取網絡,達到 state-of-the-art 的效果。
● 技術要點2 - ROIAlign
采用 ROIAlign 替代 RoiPooling(改進池化操作)。引入了一個插值過程,先通過雙線性插值到14*14,再 pooling到7*7,很大程度上解決了僅通過 Pooling 直接采樣帶來的 Misalignment 對齊問題。
PS: 雖然 Misalignment 在分類問題上影響並不大,但在 Pixel 級別的 Mask 上會存在較大誤差。
后面我們把結果對比貼出來(Table2 c & d),能夠看到 ROIAlign 帶來較大的改進,可以看到,Stride 越大改進越明顯。
● 技術要點3 - Loss Function
每個 ROIAlign 對應 K * m^2 維度的輸出。K 對應類別個數,即輸出 K 個mask,m對應池化分辨率(7*7)。Loss函數定義:
Lmask(Cls_k) = Sigmoid (Cls_k),平均二值交叉熵 (average binary cross-entropy)Loss,通過逐像素的 Sigmoid 計算得到。
Why K個mask?通過對每個 Class 對應一個 Mask 可以有效避免類間競爭(其它Class 不貢獻 Loss )。
ROIpooling
ROI pooling就不多解釋了,直接通過一個例子來形象理解。假設有一個8x8大小的feature map,要在這個feature map上得到ROI,並且進行ROI pooling到2x2大小的輸出。
假設ROI的bounding box為
如圖:
划分為2x2的網格,因為ROI的長寬除以2是不能整除的,所以會出現每個格子大小不一樣的情況。
進行max pooling的最終2x2的輸出為:
ROI Align
在Faster RCNN中,有兩次整數化的過程:
- region proposal的xywh通常是小數,為了方便操作會把它整數化。
- 將整數化后的邊界區域平均分割成 k x k 個單元,對每一個單元的邊界進行整數化。
兩次整數化的過程如下圖所示:
事實上,經過上述兩次整數化,此時的候選框已經和最開始回歸出來的位置有一定的偏差,這個偏差會影響檢測或者分割的准確度。在論文里,總結為“不匹配問題”(misalignment)。
為了解決這個問題,ROI Align方法取消整數化操作,保留了小數,使用以上介紹的雙線性插值的方法獲得坐標為浮點數的像素點上的圖像數值。但在實際操作中,ROI Align並不是簡單地補充出候選區域邊界上的坐標點,然后進行池化,而是重新進行設計。
下面通過一個例子來講解ROI Align操作。如下圖所示,虛線部分表示feature map,實線表示ROI,這里將ROI切分成2x2的單元格。如果采樣點數是4,首先將每個單元格子均分成四個小方格(如紅色線所示),每個小方格中心就是采樣點。這些采樣點的坐標通常是浮點數,所以需要對采樣點像素進行雙線性插值(如四個箭頭所示),就可以得到該像素點的值了。對每個單元格內的四個采樣點進行maxpooling,就可以得到最終的ROIAlign的結果。
參考源碼:https://github.com/matterport/Mask_RCNN
參考文獻:
https://zhuanlan.zhihu.com/p/37998710
https://www.cnblogs.com/wangyong/p/9305347.html