1. Anchor Free
Anchor 的缺點:
- 正負樣本不均衡:我們通常在特征圖所有點上均勻采樣 Anchor,而在大部分地方都是沒有物體的背景區域,導致簡單負樣本數量眾多,這部分樣本對於我們的檢測器沒有任何作用。
-
超參難調:Anchor 需要數量、大小、寬高等多個超參數,這些超參數對檢測的召回率和速度等指標影響極大。此外,人的先驗知識也很難應付數據的長尾問題,這顯然不是我們樂意見到的。
-
匹配耗時嚴重(訓練階段):為了確定每個 Anchor 是正樣本還是負樣本,通常要將每個 Anchor 與所有的標簽進行 IoU 的計算,這會占據大量的內存資源與計算時間。
這里將大致過一遍幾種主流的 Anchor Free 方法:

Figure 1
- 直接預測邊框:根據網絡特征直接預測物體出現的邊框,即上、下、左、右4個值。典型算法如 YOLOV1、利用分割思想解決檢測的 FCOS(Fully Convolutional One-Stage),以及改善了邊框回歸方式的 Foveabox 算法。
- 關鍵點的思想:使用邊框的角點或者中心點進行物體檢測,這類算法通常是受人體姿態的關鍵點估計啟發,典型有 CornerNet、ExtremeNet 及 CenterNet 等。
從目前的論文來看,Anchor-Free 的算法已經達到與基於 Anchor 的檢測器基本上旗鼓相當的程度了
2. CornerNet
code: CornerNet-Lite
paper: CornerNet: Detecting Objects as Paired Keypoints

Figure 2
CenterNet 的思想是,首先使用卷積網絡檢測整個圖像中的關鍵點的熱度圖(每一類兩個熱度圖,對應左上角和右下角,比如有10類,就是20個熱度圖。其中對於同一類的多個檢測框角點都反映在同一張熱度圖里,比如一張圖中有三只狗,那么對應狗這一類的左上角點熱度圖應該有三個位置反應強烈),然后對屬於同一個目標的關鍵點進行 group(同屬一個目標的兩個角點應該有相似的特征 embedding vector),形成檢測框。這個Embedding 的方法是借鑒了一個 NIPS17 中一個多人姿態估計的工作。考慮到下采樣取整帶來的精度損失,還要預測 Offsets 來 refine 角點的位置。檢測的基本流程如 Fig. 2 所示:

Figure 3
2.1 Network
CornerNet 的主要結構主要由以下 3 部分組成:
- 沙漏結構 Hourglass:特征提取的 Backbone,能夠為后續的網絡預測提供很好的角點特征圖。
- 角點池化:作為一個特征的池化方式,角點池化可以將物體的信息整合到左上角點或者右下角點。
- 預測輸出:傳統的物體檢測會預測邊框的類別與位置偏移,而 CornerNet 則與之完全不同,其預測了角點出現的位置 Heatmaps、角點的配對 Embeddings 及角點位置的偏移 Offsets。
如下圖所示,網絡的基礎結構單元是 nxnCBR、nxnCB、3x3Res(stride=2/stride=1, skip=3x3CB/1x1CB/直接相連)。網絡首先經過 Pre Module,下采樣兩次。然后進入兩個連續的 HG Module,訓練時兩個 HG Module 都預測輸出(虛線框部分)參與 Loss 計算,測試時只第二個人 HG Module 預測輸出(這和 GoogleNet 類似)。虛線框中包含兩種模塊:Corner Pool 和 預測模塊。兩個 Corner Pool 分別提取左上角點和右下角點的信息。

Figure 4
core/models/CornerNet.py
core/models/py_utils/modules.py
2.1.1 沙漏結構:Hourglass

Figure 5
為了提取圖像中的關鍵點,CornerNet 使用了沙漏結構 Hourglass 作為網絡特征提取的基礎模塊,其結構如上圖所示。顧名思義,Hourglass 的整體形狀類似於沙漏,兩邊大,中間小。Hourglass 結構是從
人體姿態估計領域中借鑒而來,通過多個 Hourglass 模塊的串聯,可以十分有效地提取人體姿態的關鍵點。
上圖中,左半部分表示傳統的卷積與池化過程,語義信息在增加,分辨率在減小。右半部分表示上采樣與融合過程,深層的特征通過上采樣操作與淺層的特征進行融合,在增大分辨率的同時,保留了原始的細節信息。
代碼實現采用嵌套結構,比較難懂,這里繪制了一張示意圖,方便對比代碼理解:

Figure 6
這里一個 HG Module 可以理解為 5 個嵌套的 HG Block 構成,超參數 dims 控制每個子模塊輸出 channel 數,modules 則控制每個子模塊重復次數(圖上 max1 子模塊為空)。up2 子模塊采用 nearest 插值縮放的方式上采樣。
2.1.2 角點池化:Corner Pooling
在傳統卷積網絡中,通常使用池化層來進行特征融合,擴大感受野,也可以起到縮小特征圖尺寸的作用。以3×3的最大池化層為例,通常是以當前位置的點為中心點,融合周圍共9個點的信息,取最大值輸出。
然而,CornerNet 的思想是利用左上與右下兩個關鍵點進行物體檢測,對於一個物體的左上點,其右下區域包含了物體的特征信息,同樣對於物體的右下點,其左上區域包含了物體的特征信息,這時角點的周圍只有四分之一的區域包含了物體信息,其他區域都是背景,因此傳統的池化方法就顯然不適用了。
為了達到想要的池化效果,CornerNet 提出了 Corner Pooling 的方法,左上點的池化區域是其右側與下方的特征點,右下點的池化區域是其左側與上方的特征點,如下圖所示為左上點的 Corner Pooling 過程。
在圖中,假設當前點的坐標為 (x,y),特征圖寬為 W,高為 H,則 Corner Pooling 的計算過程如下:
- 計算該點到其下方所有點的最大值,即 (x,y) 到 (x,H) 所有點的最大值。
- 計算該點到其最右側所有點的最大值,即 (x,y) 到 (W,y) 所有點的最大值。
- 將兩個最大值相加,作為 Corner Pooling 的輸出。
工程實現時,可以分別從下到上、從右到左計算最大值,這樣效率會更高。

Figure 7
Figure 3 右下角示例了提取左上角點的 Corner Pool Module 結構。
2.1.3 預測輸出:Output Prediction
最后一個重要部分就是 CornerNet 的預測輸出,以及損失的計算方式。
如圖開始那張圖所示,左上角與右下角兩個 Corner Pooling 層之后,分別接了 3 個預測量,這 3 個預測量的意義分別如下:
- Heatmaps:角點熱圖,預測特征圖中可能出現的角點,大小為 C×W×H,C 代表類別數,以左上角點的分支為例,坐標為 (c,x,y) 的預測點代表了在特征圖上坐標為 (x,y) 的點是第 c 個類別物體的左上角點的分數。
- Embeddings:Heatmaps 中的預測角點都是獨立的,而一個物體需要一對角點,因此 Embeddings 分支負責將左上角點的分支與右下角點的分支進行匹配,找到屬於同一個物體的角點,完成檢測任務,其大小為 1×W×H。
- Offsets:Offsets 代表在取整計算時丟失的精度(由於使用了降采樣,可能造成關鍵點的降采樣等效點位置離散化誤差,也就是位置精度損失),目的是進一步提升檢測的精度。這種取整的精度丟失對於小物體檢測影響很大,因此 CornerNet 引入了偏差的預測來修正檢測框的位置,其大小為2×W×H。
2.2 Preprocess
對於角點的檢測,CornerNet 對左上角和右下角分別准備了一個熱度圖,熱度圖通道數等同於類別數,尺度是輸入尺度的四分之一。后續介紹以一個熱度圖為例,另一個是同樣的操作。對於每個標注的 GT 角點,只對應到熱度圖的一個坐標位置,其余坐標位置應該作為負樣本。然而在訓練時,CornerNet 並不對所有負樣本位置做同樣的懲罰,而是以正樣本為中心,使用一個高斯函數把正樣本的分值分散給周圍的位置,也就是越接近正樣本,其作為負樣本的懲罰越小。這是因為就算沒有准確的預測到 GT 左上角和右下角,而是在其周圍分別預測到兩個角點,也是可以組成一個相對不錯的檢測框的(由於一些標注誤差,沒准還是更優的檢測框)。參考 Fig. 8 具體示例,如果兩個點的輻射區域重合了,在每個位置取數值大的那個類。

Figure 8
core/sample/cornernet.py
2.2 LOSS
CornerNet 在損失計算時借鑒了 Focal Loss 的思想,對於不同的負樣本給予了不同的權重,總體的損失公式如式(10-1)所示。
\begin{equation}
\label{loss}
L = L_{det} + \alpha L_{pull} + \beta L_{push} + \gamma L_{off}
\end{equation}
- $L_{det}$: 角點檢測的損失,借鑒了 Focal Loss 權重懲罰的思想。CornerNet 為了減小負樣本的數量,將以標簽角點為中心,半徑為 r 區域內的點都視為正樣本,因為這些點組成的邊框與標簽會有很大的 IoU,仍有可能是我們想要的正樣本。
- $L_{pull}$: Embeddings 中,對於屬於同一物體的兩個角點的懲罰。具體實現時,提取 Embeddings 中屬於同一個物體的兩個角點,然后求其均值,並希望兩個角點的值與均值的差盡可能地小。
- $L_{push}$: Embeddings中,對不屬於同一物體的兩個角點的懲罰。具體實現時,利用$L_{push}$中配對的角點的平均值,期望沒有配對的角點與該平均值的差值盡可能地大(loss 設計中以保證距離大於1),可以有效分離開無效的角點。
- $L_{off}$: 位置偏差的回歸損失,與 SSD 相似的是,CornerNet使用了 smoothL1 損失函數來優化這部分位置偏差。
core/models/py_utils/losses.py
2.3 Postprocess
這里用最大池化取代了 NMS 操作:
- tl_heat 和 br_heat 經過 sigmoid 平滑處理
- heatmaps 做了一個類 NMS 操作,即用 3x3 的 maxpool(stride=1, pad=1) 尋找亮點,heatmaps 中只保留亮點位置處的值(其他置0)
- 分別選擇 top100 個 heatmaps 亮點作為目標頂點候選點,這樣的話存在 100x100 種組合
- 根據候選點位置解碼左上角和右下角頂點位置
- 匹配兩類頂點,類別不同的排除,Embedding 差距大於 ae_threshold(0.5, 訓練時要保證大於1) 的排除,左上角和右下角位置不符合空間位置關系的排除
- 最后只保留 top1000 對頂點組合作為檢測目標
CornerNet在推理時也不會resize輸入圖像,而是直接使用原始尺寸輸入。並且會使用原始圖像和翻轉的圖像同時預測,並融合預測結果來提高准確率。
core/models/py_utils/utils.py
3. CenterNet
code: CenterNet
paper: Objects as Points

Figure 9
CenterNet 算是 CornerNet 的拓展版,其核心思想是:
- 將 GT 通過高斯核將目標以 GT 中心點為中心輻射到整個圖像平面(目標中心點處值為1,距離中心點位置越遠值越小,多個目標中心點輻射有重疊的部分取數值較大的那個)形成熱力圖形式的 GT (算是一種 label smooth);
- 然后在輸出 feature map 上分別預測 C個類別+2維的寬高尺寸+2維中心點偏移 三個 modality,每個 modality 在 feature map 的基礎上分別經過一個 3x3 卷積 + ReLU + 1x1 卷積的組合來預測;
- 推理時,對於每一個類別的結果(一片熱力圖),首先在輸出熱度圖上找到尖峰點,即熱度值大於等於其8個相鄰鄰居的點。保持100個熱度圖取值最大的尖峰點,並用其取值直接表示置信度得分。對每個點的坐標,加上預測局部偏移量,以及以其為中心的尺寸擴展,得到矩形框四個角點。
- 作者接着又雙叒叕提到了 CenterNet 后續不需要基於 IoU 的NMS或其他后處理。作者認為尖峰點的提取已經足以作為非極大抑制的替代品了,直接做一個非常高效的 3x3 最大池化就相當於 NMS 了 (也就是說如果兩個尖峰點在熱度圖上距離兩個像素以上就認為是兩個物體了)。
3.1 Network

Figure 10
- 網絡結構上,backbone 除了 Hourglass、ResNet 此類外作者還引入了 DLA 模塊,即使用 deformable 卷積來跳躍連接低層和輸出層。
- Head 部分接 3 組 3x3 卷積,分別預測分類熱力圖、目標框的寬高以及回歸框偏移(由於下采樣取整操作等會導致中心點偏移)三個量。
src/lib/models/model.py
3.2 Preprocess
為了形象描述,這里用自己的數據集(12 個類別)展示后續過程,訓練輸入尺度固定為 320x480
1. 圖像先經過變換到訓練尺度
2. 根據 GT 分布得到以下幾個量:
- hm: 12x80x120 維度,輸出尺度上,對應 12 個類別的 GT 熱力圖,每個人熱力點中心(值為1)為目標在輸出尺度上的中心點。以下圖某一類別的 GT 分布為例,第二行描述的是最后一個目標:
- wh: 輸出尺度上,目標的實際寬和高
- reg: 輸出尺度上,因為下采樣取整導致的精回歸誤差(回歸目標=實際中心坐標 - 取整后中心點坐標)
src/lib/datasets/dataset_factory.py
src/lib/datasets/dataset/coco.py
src/lib/datasets/sample/ctdet.py
3.3 Loss
- 分類采用 FocalLoss, 回歸均采用 RegL1Loss。使用 FocalLoss 時,hm 需要經過 sigmoid 函數平滑處理
- 這里的 FocalLoss 不同於原版,我們知道 FocalLoss 的定義形式是:
\begin{equation}
\label{FocalLoss}
FL(p_t) = -\alpha_t (1-p_t)^{\gamma} log(p_t)
\end{equation}
這里 $\gamma=2$, $\alpha_t = (1-p_t)^4$,以上面的點為例,負樣本的 $\alpha$ 可視化權重為
- 作者實驗中,分類、高寬回歸和中心點回歸三個部分的 loss 比例分別是 1:0.1:1
src/lib/trains/base_trainer.py
src/lib/trains/ctdet.py
src/lib/models/losses.py
3.4 Postprocess
- hm 經過 sigmoid 平滑處理
- hm 做了一個類 NMS 操作,即用 3x3 的 maxpool(stride=1, pad=1) 尋找亮點,hm 中只保留亮點位置處的值(其他置0)
- 選擇 top100 個 hm 亮點作為目標候選點
- 根據候選點位置解碼出目標包圍框
src/lib/detectors/ctdet.py
src/lib/models/decode.py
4. FCOS
code: FCOS
paper: FCOS: Fully Convolutional One-Stage Object Detection

Figure 11
4.1 網絡結構

Figure 11
1. 網絡結構上,如上圖所示:FCOS 共 5 個尺度輸出 {$P_3, P_4, P_5, P_6, P_7$},其中 $P_3, P_4, P_5$ 由 backbone 中的 feature map $C_3, C_4, C_5$ 經過一個1x1卷積橫向連接得到。
2. 同 FPN、RetinaNet 一樣,模型中共享 heads 部分的參數,這樣不僅可以使檢測器更參數高效,而且也可以提升檢測性能。同時這里還采用了 GroupNorm 層代替了 BatchNorm。
3. 具體的,每個 feature map 先分別進入 cls_tower 和 bbox_tower 兩個模塊分離類別特征和位置特征。每個尺度分離出來的類別特征經過一個 3x3 卷積預測 classification score,區別於 yolov3 有一個區分前景背景的 score,這里換成了一個 3x3 卷積預測 score,目的都是為了抑制低質量的預測框,但分類目標的物理意義不同(yolov3 是全局做分類(有大量負樣本),centerness 是同回歸一樣只在正樣本集合里做分類)。在分類分支上加上一個 $1D$ 的分類分支,分類目標是個 smooth 形式:
\begin{equation}
\label{centerness}
centerness^* = \sqrt{\frac{min(l^*, r^*)}{max(l^*, r^*)} \times \frac{min(t^*, b^*)}{max(t^*, b^*)}}
\end{equation}
采用 BCE Loss, 該 loss 加到 3.4 節的 Eq.3 上。訓練時 centerness target 作為權重項給予回歸 loss,預測時,最終的分類 score 由分類分支的分數和 "centerness" 分支的分數相乘獲得(訓練時沒有該操作)。目的是為了降低那些遠離目標中心的檢測框的分數,隨后這些低質量檢測框可以通過 NMS 去除。當然中心化操作也可以通過限定 GT 中心的附近的點/Anchor 作為正樣本來達到。
4. 正常情況下分離出的位置特征則只需要經過一個 3x3 卷積來預測中心點到四邊的距離。但考慮到不同尺度的回歸范圍不同,模型中考慮利用 $exp(s_i*x)$ 操作來標准化,對回歸分支上$(0,+\infty)$的所有實數預測做映射,其中 $s_i$ 是學習出來的,這對提升模型性能很重要。
fcos_core/modeling/detector/generalized_rcnn.py
fcos_core/modeling/rpn/fcos/loss.py
4.2 Preprocess
1. feature map 上,所有落在 bbox 內的 (x,y) 都將被視為正樣本,回歸目標是該位置到 bbox 的四個邊框(映射到 feature map 上)的距離, 這就相當於是一個框級別的實例分割了:
\begin{equation}
\label{regression target}
\begin{split}
& l^* = x - x_0^{(i)}, \ t^* = y - y_0^{(i)} , \\
& r^* = x_1^{(i)} - x, \ b^* = y_1^{(i)} - y . \\
\end{split}
\end{equation}
2. 對於落在重疊框里的點 (x,y) 則簡單選擇面積最小的那個作為回歸目標/分類目標。
3. 區別於 Anchor based 檢測器中,通過在不同尺度 feature map 中設置不同大小的 Anchor boxes 來完成多尺度,這里直接限制 bounding box regression。具體的,每個尺度分別限定它們的預測范圍為 $P_3$ [0, 64], $P_4$ [64, 128], $P_5$ [128, 256], $P_6$ [256, 512], $P_7$ [512,$+\infty$]。因為不同尺寸的目標被分配到不同特征層上,而大部分重疊都發生在尺寸差異比較大的目標之間,所以 multi-level prediction 可以緩解上文提到的二義性問題,提高 FCN based 檢測器的性能,使之接近 Anchor based 檢測器。特別的,如果還存在對應多個 GT 的實例,就簡單取面積最小的那個 GT 為目標就好了。 ps. 這種限制理論上有意義,但實際使用效果如何待驗證。
fcos_core/data/datasets/coco.py
fcos_core/data/build.py
fcos_core/modeling/rpn/fcos/loss.py
4.3 Loss
1. 用訓練 $C$ 個 binary classifiers 代替訓練一個 multi-class classifier。
2. $L_{cls}$ 是有 focal loss 加成的,$L_{reg}$ 是 IoU loss。$N_{pos}$ 代表正樣本的數量,$\lambda$ 是一個權重因子(論文中設為1)。$\textbf{1}_{c_i^*>0}$ 是一個指標函數,當 $c_i^*>0$ 值為1,否則為0:
\begin{equation}
\label{loss function}
L(\{p_{x,y}\},\{t_{x,y}\}) = \frac{1}{N_{pos}}\sum_{x,y}{L_{cls}(p_{x,y}, x_{x,y}^*)} + \frac{\lambda}{N_{pos}}\sum_{x,y}{\textbf{1}_{\{c_i^*>0\}} L_{reg}(t_{x,y}, t_{x,y}^*)}
\end{equation}
當然,還有一個 3.1 節描述的 centerness 分類loss,代碼中發現,回歸 Loss 不是用 $N_{pos}$ 作歸一化的,而是用 $\sum{centerness}$。
fcos_core/modeling/rpn/fcos/loss.py
4.4 Postprocess
- 先用 pre_nms_thresh 閾值過濾掉低 cls_score 框
- 將 classification scores 和 centerness scores 相乘來更新 classification scores
- 按照 classification scores 排序獲得前 per_pre_nms_top_n = min(pre_nms_top_n, sum(cls_remain)) 個預測框
- 將 box_regression 預測結果和中心點位置 meshgrid 結合,將坐標映射到原圖,獲得 (xmin, ymin, xmax, ymax) 回歸框
- 過濾掉特別小的框(min_size)
- 最后,由於是多尺度預測,因此 NMS 還是少不了的
fcos_core/modeling/rpn/fcos/fcos.py
fcos_core/modeling/rpn/fcos/inference.py
5. Summary
1. 從我個人的理解來看,這三篇論文其實都是從分割角度來解決目標檢測這一問題的。CornerNet 和 CenterNet 分別在兩個頂點和一個中心點處設計一個高斯熱力圖 GT,兩個算法通過 CxHxW 維度的 heatmap 完成 C 個類別的語義分割, 而由於 CornerNet 用兩個頂點描述一個框,因此需要通過 Embedding 來完成兩個頂點的配對。區別於前兩個算法用點擴散成的熱力圖作為 GT,FCOS 則是將最后的 feature map 里所有落在 GT 內的點都作為正樣本。
2. CornerNet 通過兩個頂點預測定位目標位置,CenterNet 則通過中心點和寬高預測來定位目標位置,但考慮到下采樣取整此類的操作,理論上就是 stride(4)-1 個像素誤差存在,因此 CornerNet 和 CenterNet 網絡還預測了一個 offsets(2xHxW)。區別於前兩個算法 FCOS 則是通過預測點(不一定是中心點)到框四個邊界的距離來完成目標定位。
3. CornerNet 引入的 Embedding 預測如果不准那會帶來額外的誤差問題。
4. CornerNet 和 CenterNet 都用最大池化操作來代替 NMS 操作,效率更高
5. FCOS 用到了多尺度,同時通過直接限制 bounding box regression 將不同尺寸的目標被分配到不同特征層上來解決重疊目標檢測的問題(作者認為大部分重疊都發生在尺寸差異比較大的目標之間)
6. FCOS 這里引入了 Center-ness 分類器(smooth 形式),預測時加權到類別分數上(類似於 YOLOV3 這種有一個預測是前景還是背景的分類器),訓練時則加權到回歸器上,目的是為了去掉遠離目標中心的重疊框。
Reference
1. 深度學習之 PyTorch 物體檢測實戰
