二階段目標檢測總結
概述:
最新幾年的論文都是在單階段、Transform上進行發掘提升,基本上2020-2021年二階段論文全軍覆沒,這篇博文也是總結2016-2019年的發展,最後一篇CenternetV2比較特殊,不能完全算作傳統意義的二階段網路。
目前什麼地方還使用二階段論文?
- 比賽場景,經常使用FasterRCNN的變種+其它網路進行聯合預測
- 目標比較小的場景(使用較少,一般用anchor-free、增大輸入去代替、分割影象檢測)
- 輔助一階段使用,和(2)類似但不同。比如檢測遠距離人形+人臉,方案一:先檢測人,後檢測人臉,兩個都是OneStage。方案二:使用TwoStage網路,第一階段檢測人形,第二階段檢測人臉。當然只有第二類別是第一類別的從屬,且是唯一關係才能進行!
一. FasterRCNN
以torchvision給出的demo為例子:
- 第一階段,和基礎SSD等一階段操作類似,但是這一階段會立刻輸出候選區域
-
將候選區域從FPN輸出的feature上摳出來
-
使用ROIPooling對齊候選特徵的大小
- 第二階段,直接進行FC細化Reg/Cls,當然這裡只能是一個候選區域最多一個目標。
class FastRCNNPredictor(nn.Module): """ Standard classification + bounding box regression layers for Fast R-CNN. Args: in_channels (int): number of input channels num_classes (int): number of output classes (including background) """ def __init__(self, in_channels, num_classes): super(FastRCNNPredictor, self).__init__() self.cls_score = nn.Linear(in_channels, num_classes) self.bbox_pred = nn.Linear(in_channels, num_classes * 4) def forward(self, x): if x.dim() == 4: assert list(x.shape[2:]) == [1, 1] x = x.flatten(start_dim=1) scores = self.cls_score(x) bbox_deltas = self.bbox_pred(x) return scores, bbox_deltas
註釋:
- 最後一步FC是參考anchor的做法,首先想到的是\(self.bbox\_pred = nn.Linear(in\_channels,4)\) ,因為已經使用class進行了過濾,沒有必要再把regression去使用class再去過濾一遍。當然使用class對迴歸進行區分,這效果肯定優於單個迴歸。
- 我們再進一步延伸,如果在不同的class之下,再使用一種手段(長寬、面積、anchor等)對其進一步劃分,比如:假設候選區域數量不變為 \(P\),類別為兩類(人形、人臉),進一步使用anchor限制(兩個anchor,5和20,比例4倍以內使用5,超過4倍使用20),這樣會不會更精細?
- 上一步我們限制了候選區域數量,能不能使用輸入多個不同組的候選區域,後面連線多個不同的predict?這就是後續改進cascadeRCNN的由來。
二. MaskRCNN
- 第一階段使用FasterRCNN,RPN網路都相同
- 第二階段輸出多一個分支 \(K\times m\times m\) , 其中 \(K\) 表示種類,\(m\) 表示輸出解析度
注意: 最後輸出的mask大小是固定的,設定大小得根據實際種類而定。這個mask分支和FCN有點區別,這裡使用K個feature,然後直接進行二分類操作,而FCN使用單個feature進行多分類操作,目前檢測的分類loss都是進行單獨的二分類操作。
三. CascadeRCNN
-
第一階段和FasterRCNN完全一樣
-
第二階段使用多個RoiHead層進行級聯
下圖完全顯示了CascadeRCNN的由來
- 下圖(C)僅僅在前向計算的時候使用級聯finetune操作,精度也得到一定提升,但是有兩個缺陷。1)使用共享的Head-H1,不僅時間沒降低,而且引數效果還不好。所以在端側單階段目標檢測中,一般不使用共享的頭,雖然引數減少了,但是計算量一點未變,所以都使用不共享的頭。2)都是固定的,不能進行訓練,後面的階段已經處於過擬合狀態。
- 下圖(d)最大的缺點就是候選區域固定,非常容易過擬合。有一個優點,後面的stage僅僅進行分類而不進行reg,這是cascade未考慮的。但是,分類分支花費的代價很小,基本影響不到大局,所以討論的人很少。
- 下圖(b)融合了兩者的優點,1)可訓練。2)不共享。3)候選區域不同。
四. Libra RCNN
未改變實際的流程結構,文章從均衡的角度對各個模組進行改進。
- \(feature\) 均衡,使用FPN、PAN、BiFPN進行互相連結
- 取樣均衡,原始SSD分配使用Max-IOU,取樣使用Random-Sample
- loss均衡,原始SSD直接使用獨立的分支進行計算
IOU-Balance取樣,下圖是困難負樣本(\(Iou<0.5\) 稱為困難負樣本)的Iou分佈,其中64%樣本\(Iou>0.05\),36%的樣本\(Iou<0.05\),注意這裡是百分比圖,不是個數量圖!!!下圖中使用隨機取樣,會導致70%的樣本\(Iou<0.05\) ,這明顯是不符合下圖的困難負樣本的分佈圖的。如何將下附圖的每個方格取樣比例趨於平衡?很明顯的想到還是使用方格將IOU進行區域劃分(直方圖的表示方法),然後按照一定比例進行取樣即可。論文給出一些控制引數,使得表達更為通俗易懂。
關於feature部分的平衡,這部分有點玄,意義不大。。。
關於loss的平衡,主要對smooth-L1進行調整,文章分析了loss的貢獻率,\(loss<1.0\) 貢獻30%,相反貢獻70%,既然要平衡,那就要提升 \(loss<1.0\) 的梯度(loss佔比),其實和focal-loss一樣,都是提升困難樣本的比重。
\[L_{b}(x)=\left\{\begin{array}{ll} \frac{\alpha}{b}(b|x|+1) \ln (b|x|+1)-\alpha|x| & \text { if }|x|<1 \\ \gamma|x|+C & \text { otherwise } \end{array}\right. \]五. GridRCNN
- 第一階段和FasterRCNN完全一樣
- 分類分支相同,迴歸分支使用關鍵點
從當前的角度看,這篇論文較為簡單,屬於簡化版的anchor-free模型,因為是對候選區域進行操作,不需要anchor的匹配,不需要進行nms等操作。和top-bottom的pose估計一模一樣!!
如果把第一階段也使用關鍵點去估計,那這篇二階段文章就完全是anchor-free+pose的文章了。
需要注意一點,經常出現候選區域把目標截斷(二階段網路都存在的問題),那關鍵點就不存在(使用0表示),但是對於定位就很不準確。最簡單的方式是直接擴大候選區域的截圖範圍,作者嘗試這種方案效果不理想。作者採用候選區域不變,僅對候選迴歸框做擴大。如下圖所示,綠色是目標框,白色實線是候選框,輸入白色實線候選區域,在白色虛線的基礎上進行迴歸。
GridRCNN-V2
- 第一階段和FasterRCNN完全一樣
- 第二階段和GridRCNN-V1基本相同
這篇論文主要是對第一版本的速度進行改進:
- keypoint branch 從\(56\times56\)降低到\(28 \times 28\) ,論文說這樣做不僅會加快速度,而且還會提高精度。之前在關鍵點上試驗,使用期望定位會有精度損失。
- 減小候選區域的大小,降低channels
- 聯合整個batch影象進行計算。之前使用for迴圈,單次計算單張影象,對於目標數量非常敏感,現在是對batch進行一次計算。
- NMS僅進行一次
六. CenterNetV2
在剛開始的概述(3)中,表達了一種二階段網路的特殊應用,這篇文章將此應用表述成一種方案:我們可以使用任何一階段的網路作為RPN層(包括anchor-based、anchor-free操作),後面ROI階段可以使用任何之前的第二階段網路。這不就是集合前人的大雜燴?搞不懂為啥沒有使用YOLOV4作為第一階段進行比較?
進一步引申:
- 類似人形+人臉的檢測組合(概述3)
- 關鍵點檢測模型(Top-Bottom),比如人體關鍵點估計,可以直接使用二階段網路。