論文: YOLACT: Real-Time Instance Segmentation
0.簡介
慣例,有請作者自己介紹一下本文工作——摘要:
-
是一個fully-convolutional模型
-
29.8mAP——COCO, 33.5fps——a TitanXP。
(精度高於FCIS,低於MaskRCNN之后的。但速度猛提,注意,MaskRCNN僅為為5fps。)
-
分為兩個平行子任務:
- 生成一系列Prototype masks
- 預測mask coefficients
然后兩者線性結合(矩陣相乘)得出instance masks
-
提出Fast NMS,微小代價換來12ms增速
YOLACT——You Only Look At CoefficienTs,是實力分割單階段的一個代表算法,不論是模型名字還是原文第一段直接引用Joseph Redmon在YOLOv3中的原話,都致敬了目標檢測領域的YOLO,可見他的目標就是real-time。
1.YOLACT結構
首先,圖像經過主干網絡提取特征,這里使用的是ResNet101-FPN。圖中下面的分支,使用FPN的P3輸出作為Protonet的輸入產生與在原圖上全局的k個prototypes(P3同時擁有深層特征有較好魯棒性以及高分辨率有利於提升Mask質量及小目標精度的特點);同時上面的分支,除了進行典型目標檢測的框分類及回歸系數之外,還將對每個anchor預測出k個系數cofficients,即每個prototype的系數。然后組裝prototypes和cofficients,再進行剪切和閾值處理就得到了instance masks。
2.Prototypes
用於生成prototypes的Protonet分支為全卷積網絡,在上一節說過,protonet選擇了使用FPN的p3特征作為輸入。特征深則魯棒性好,特征圖大則mask質量高且小目標精度好,想要特征圖又深又大,所以作者選擇了FPN。
正如上圖,除了最后一個卷積為1×1,其他卷積都為3×3,使用ReLU作為激活函數,對於550×550的圖像,最終會產生k個138×138的全局prototypes。 這種方法類似語義分割方法,但不同的是,沒有對生成prototypes單獨設置loss來懲罰,而是通過組成之后的loss來監督。
上圖即為產生的prototypes,網絡學習出產生的protoypes都有一些明顯的功能,例如1-3是一些粗糙、隱式的一側邊界,4對圖像下部一些對象做出了反應,5反映背景,6感知圖像中的地面,等等。
另外,作者提到,因為有些prototype的功能是相近的,所以K=32就夠用,而且k=32時效果就幾乎飽和了,不會隨着K的增加而增加,因為k變大,預測其cofficients也變的困難。
3.Coefficients
預測cofficients的分支,是在目標檢測經典結構上增改而來的,原有框分類和回歸的兩個分支,YOLACT的head加入第三個分支來預測cofficients,每一個coofficient數值對應一個prototype,原本對於每個anchor預測的區域需要預測c+4個數,現在需要c+4+k個,圖中的a為每個像素產生多少個anchor(對anchor不熟悉的可以去學習下fasterrcnn的論文),本文a=3。
簡單來說就是,對於每個anchor的區域,產生k個系數(cofficients),每個系數對應一個prototype,即是最后通過線性運算組裝這k個prototypes的每個prototype前面的系數。當然除此之外對於每個anchor還要產生分類及回歸的系數。
具體來說,我們來詳細計算一下參數:
輸入的特征圖先生成 anchor。每個像素點生成 3 個 anchor,比例是 1:1、1:2 和 2:1。五個特征圖的 anchor 基本邊長分別是 24、48、96、192 和 384。基本邊長根據不同比例進行調整,確保 anchor 的面積相等。
上圖是p3-p7其中某一個對應的head,每一個特征圖分支都對應上圖這樣一個head結構。
接下來以 P3 為例,標記它的維度為 W3×H3×256,那么它的 anchor 數就是 a3 = W3×H3×3。接下來 Prediction Head 為其生成三類輸出:
-
類別置信。因為 COCO 中共有 81 類(包括背景),所以其維度為 a3×81;
-
位置偏移,維度為 a3*4;
-
mask coefficient,維度為 a3*32。
對 P4-P7 進行的操作是相同的,最后將這些結果拼接起來,標記 a* = a3 + a4 + a5 + a6 + a7,得到:
- 全部類別置信。因為 COCO 中共有 81 類(包括背景),所以其維度為 a*×81;
- 全部位置偏移,維度為 a*×4;
- 全部 mask coefficient,維度為 a*×32。
4. InstanceMasks組裝
得到prototypes和cofficients后我們使用如下公式實現線性組合以及非線性化——進行組裝:
先矩陣相乘再對結果sigmoid。其中P是prototype masks矩陣,為h×w×k,C是n個在NMS(其實是作者提出的Fast NMS,為了介紹YOLACT思路流暢,我把FastNMS放在下一節介紹,這里可以先認為是NMS,作用是一樣的)以及得分閾值存活下來的實例對應的cofficients矩陣,為n×k。結果M為h×w*n,即n個實例,每個都有一張h×w的全局結果。
最后剪切實例Masks,在訓練時,使用groud truth的bounding box來切割;在驗證時,使用預測的bounding box來切割。切割后根據設定的閾值,進行實例的二值化,將實例與背景分開。
loss fuction
其中前兩項為框分類及回歸的loss,使用了SSD中設計的loss function。最后一項關於Mask的loss本文設計為,是結果M與GroudTruth之間的pixel-wise二分類交叉熵,即:
計算時,是用ground truth的bounding box分成每個區域進行計算,以能夠在prototype中保留小的物體。
5.Fast NMS
Fast NMS算法的操作,知乎Yang Xuangan的文章通過具體例子的方式講解非常易懂:
經過本文第3節中Head網絡,得到位置偏移后,可以通過 anchor 的位置加上位置偏移得到 RoI 位置。然后FastNMS(代替傳統NMS)去掉冗余的ROI。
為了便於理解,下面依舊舉例說明FastNMS。假設我們有 5 個 RoI,對於 person 這一類,按照置信度由高到低分別是 b1、b2、b3、b4 和 b5。接下來通過矩陣運算得出它們彼此之間的 IoU,假設結果如下:
接下來將這個矩陣的下三角和對角線元素刪去,得到下面的結果:
這其中的每一個元素都滿足行號小於列號。接下來對每一列取最大值,得到 [-, 0.8, 0.6, 0.6, 0.4]。假設閾值為 0. 5,即 IoU 超過 0.5 的兩個 RoI 需要舍棄掉置信度低的那一個。根據最大值,b2、b3 和 b4 對應的列都超出了閾值,所以這三個 RoI 會在這一步舍去。
這樣做的原因是,由於每一個元素都是行號小於列號,而序號又是按照置信度從高到低降序排列的,因此任一元素大於閾值,代表着這一列對應的 RoI 與一個比它置信度高的 RoI 過於重疊了,需要將它舍去。
這里需要注意的是,b3 雖然和 b2 過於重疊(IoU 為 0.6),但 b3 與 b1 的 IoU 只有 0.1,而 b2 與 b1 的 IoU 為 0.8。按照傳統 NMS 算法,b2 會在第一輪循環中被舍去,這樣 b3 將會被保留。這也是 Fast NMS 與 NMS 不同的地方,即原文所述:we simply allow already-removed detections to suppress other detections, which is not possible in traditional NMS.
如上圖所示,FastNMS用微弱的效果代價還換取了較大的速度提升。
6.代碼 實驗
文章比較新,官方開源代碼就是pytorch1.0的,整體結構清晰明了,閱讀學習、運行都可直接使用。我用ResNet101-FPN在COCO上訓練,50epoch后准確率如下,速度為9.87fps?(2080Ti)
all | .50 | .55 | .60 | .65 | .70 | .75 | .80 | .85 | .90 | .95 | |
---|---|---|---|---|---|---|---|---|---|---|---|
box | 31.63 | 51.22 | 48.92 | 46.01 | 42.76 | 38.77 | 33.46 | 27.19 | 18.76 | 8.15 | 1.03 |
mask | 29.31 | 47.50 | 44.84 | 42.13 | 38.81 | 35.05 | 30.62 | 25.26 | 18.07 | 9.21 | 1.64 |
參考及引圖: