聲明:本文大部分參考機器之心的文章《從RCNN到SSD,這應該是最全的一份目標檢測算法盤點》,僅作為學習之用,如若侵權,請馬上聯系我刪除。(另外,強烈安利機器之心,文章質量都非常高!)
=======================================================================
目標檢測是很多計算機視覺任務的基礎,不論我們需要實現圖像與文字的交互還是需要識別精細類別,它都提供了可靠的信息。本文對目標檢測進行了整體回顧,第一部分從 RCNN 開始介紹基于候選區域的目標檢測,包括 Fast R-CNN、Faster R-CNN 和 R-FCN 等;第二部分則重點討論了包括 YOLO、SSD 和 RetinaNet 等在內的單次檢測器,它們都是目前最為優秀的方法。
目標檢測目前有 one-stage 和 two-stage 兩種,two-stage 指的是檢測算法需要分兩步完成,首先需要獲取候選區域,然后進行分類,比如R-CNN系列;與之相對的是 one-stage 檢測,可以理解為一步到位,不需要單獨尋找候選區域,典型的有SSD/YOLO。
一、基于候選區域的目標檢測
1. 滑動窗口檢測器
自從 AlexNet 獲得 ILSVRC 2012 挑戰賽冠軍后,用 CNN 進行分類成為主流。一種用于目標檢測的暴力方法是從左到右、從上到下滑動窗口,利用分類識別目標。為了在不同觀察距離處檢測不同的目標類型,需要使用不同大小和寬高比的窗口。
我們根據滑動窗口從圖像中剪切圖像塊。由于很多分類器只取固定大小的圖像,因此這些圖像塊是經過變形轉換的。但是,這不影響分類準確率,因為分類器可以處理變形后的圖像。
變形圖像塊被輸入 CNN 分類器中,提取出 4096 個特征。之后,我們使用 SVM 分類器識別類別和該邊界框的另一個線性回歸器。
下面是偽代碼。我們創建很多窗口來檢測不同位置的不同目標,要提升性能,一個顯而易見的辦法就是減少窗口數量。
for window in windows:
patchs = get_patch(image, window)
results = detector(patchs)
2. R-CNN
實際上,更實用的方法是候選區域(Region Proposals )方法來獲取感興趣的區域(ROI)。選擇性搜索(Selective Search )就是一種典型的候選區域方法。算法原理如下:首先將每個像素作為一組。然后,計算每一組的紋理,并將兩個最接近的組結合起來。但是為了避免單個區域吞噬其他區域,我們首先對較小的組進行分組。我們繼續合并區域,直到所有區域都結合在一起。下圖第一行展示了如何使區域增長,第二行中的藍色矩形代表合并過程中所有可能的 ROI。與尋找幾乎個區域比起來,這種方法要高效的多。
R-CNN 利用候選區域方法創建了約 2000 個 ROI。這些區域被轉換為固定大小的圖像,并分別送到卷積神經網絡中。之后使用SVM對區域進行分類,使用線性回歸損失來校正邊界框,以實現目標分類并得到邊界框。以下是 R-CNN 整個系統的流程圖:
通過使用更少且更高質量的 ROI,R-CNN 要比滑動窗口方法更快速、更準確。偽代碼如下:
ROIs = region_proposal(image)
for ROI in ROIs
patch = get_patch(image, ROI)
results = detector(patch)
3. Fast R-CNN
R-CNN 需要非常多的候選區域以提升準確度,但其實有很多區域是彼此重疊的。如果我們有 2000 個候選區域,且每一個都需要獨立地饋送到 CNN 中,那么對于不同的 ROI,我們可能需要重復提取很多次特征。因此 R-CNN 的訓練和預測速度非常慢。
此外,CNN 中的特征圖以一種密集的方式表征空間特征,那么我們能直接使用特征圖代替原圖來檢測目標嗎?答案是肯定的。
Fast R-CNN 使用CNN網絡先提取整個圖像的特征,而不是對每個圖像塊提取多次。然后,我們可以將創建候選區域的方法直接應用到提取到的特征圖上。例如,Fast R-CNN 選擇了 VGG16 中的卷積層 conv5 來生成 ROI區域在對應的特征圖上的映射特征圖塊,并用于目標檢測任務中。我們使用 ROI 池化將特征圖塊轉換為固定的大小,并送到全連接層進行分類和定位。因為 Fast-RCNN 不會重復提取特征,所以它能顯著地減少處理時間。
以下是 Fast R-CNN 的流程圖:
ROI 池化
因為 Fast R-CNN 使用全連接層,所以我們應用 ROI 池化將不同大小的 ROI 轉換為固定大小。比如我們將 8×8 特征圖轉換為預定義的 2×2 大小:
左上角:輸入特征圖;
右上角:將 ROI(藍色區域)與特征圖重疊;
左下角:將 ROI 拆分為目標維度。例如,對于 2×2 目標,我們將 ROI 分割為 4 個大小相似或相等的部分;
右下角:找到每個部分的最大值,得到變換后的特征圖。
按上述步驟得到一個 2×2 的特征圖塊,可以送至分類器和邊界框回歸器中。使用softmax損失進行分類;使用回歸損失比如平滑L1損失校正包圍框。總損失是兩部分的和,然后反向傳播進行訓練。Fast R-CNN 最重要的一點就是包含特征提取器、分類器和邊界框回歸器在內的整個網絡能通過多任務損失函數進行端到端的訓練,這種多任務損失即結合了分類損失和定位損失的方法,大大提升了模型準確度。
在下面的偽代碼中,計算量巨大的特征提取過程從 For 循環中移出來了,因此速度得到顯著提升。Fast R-CNN 的訓練速度是 R-CNN 的 10 倍,預測速度是后者的 150 倍。
feature_maps = process(image)
ROIs = region_proposal(feature_maps)
for ROI in ROIs
patch = roi_pooling(feature_maps, ROI)
results = detector2(patch)
4. Faster R-CNN
Fast R-CNN 依賴于外部候選區域方法,如選擇性搜索。但這些算法在 CPU 上運行且速度很慢。在測試中,Fast R-CNN 需要 2.3 秒來進行預測,其中 2 秒用于生成 2000 個 ROI。因此區域生成的計算成為整個檢測網絡的瓶頸。
與其使用固定的算法得到候選區域,不如讓網絡自己學習自己的候選區域應該是什么。因此,Faster R-CNN 采用與 Fast R-CNN 相同的設計,只是它用區域生成網絡(Region Proposal Network,RPN)代替了候選區域方法。新的候選區域網絡(RPN)在生成 ROI 時效率更高,并且以每幅圖像 10 毫秒的速度運行。
RPN
區域生成網絡(RPN)將前面卷積網絡的輸出特征圖作為輸入,比如VGG16的conv5特征圖。它在特征圖上滑動一個 3×3 的卷積核,以使用卷積網絡構建與類別無關的候選區域。使用VGG網絡提取特征的話,每個 3x3 區域會得到一個512維的特征向量,然后送到兩個獨立的全連接層,以預測邊界框和兩個目標分數(是目標或者不是目標)。我們其實可以使用回歸器計算單個 目標分數,但為簡潔起見,Faster R-CNN 使用只有兩個類別的分類器:即帶有目標的類別和不帶有目標的類別。
對于特征圖中的每一個位置,RPN 會做 k 次預測。因此,RPN 將輸出 4×k 個坐標和每個位置上 2×k 個得分。下圖展示了 8×8 的特征圖,且有一個 3×3 的卷積核執行運算,它最后輸出 8×8×3 個 ROI(其中 k=3)。下圖(右)展示了單個位置的 3 個候選區域。
上圖每個位置有 3 種猜想,稍后我們將予以完善。由于只需要一個正確猜想,因此我們最初的猜想最好涵蓋不同的形狀和大小。因此,Faster R-CNN 不會創建隨機邊界框。相反,它會預測一些與左上角名為錨點的參考框相關的偏移量(如??x、??y)。要對每個位置進行 k 個預測,我們需要以每個位置為中心的 k 個錨點。這些錨點是精心挑選的,因此它們是多樣的,且覆蓋具有不同比例和寬高比的現實目標。這使得我們可以以更好的猜想來指導初始訓練,并允許每個預測專門用于特定的形狀。每個預測與特定錨點相關聯,但不同位置共享相同形狀的錨點。
Faster R-CNN 使用更多的錨點。它部署 9 個錨點框:3 個不同寬高比的 3 個不同大小的錨點框。每一個位置使用 9 個錨點,每個位置會生成 2×9 個目標分數和 4×9 個坐標。
偽代碼:
feature_maps = process(image)
ROIs = rpn(feature_maps)
for ROI in ROIs
patch = roi_pooling(feature_maps, ROI)
class_scores, box = detector(patch)
class_probabilities = softmax(class_scores)
這部分詳細的內容可以參考:Faster R-CNN:使用RPN實時目標檢測
5. F-RCN
R-FCN 通過減少每個 ROI 所需的工作量實現加速。上面基于區域的特征圖與 ROI 是獨立的,可以在每個 ROI 之外單獨計算。剩下的工作就比較簡單了,因此 R-FCN 的速度比 Faster R-CNN 快。
feature_maps = process(image)
ROIs = region_proposal(feature_maps)
score_maps = compute_score_map(feature_maps)
for ROI in ROIs
V = region_roi_pool(score_maps, ROI)
class_scores, box = average(V) # Much simpler!
class_probabilities = softmax(class_scores)
二、One-Stage 目標檢測
這部分我們將對單次目標檢測器(包括 SSD、YOLO、YOLOv2、YOLOv3)進行綜述。我們將分析 FPN 以理解多尺度特征圖如何提高準確率,特別是小目標的檢測,其在單次檢測器中的檢測效果通常很差。然后我們將分析 Focal loss 和 RetinaNet,看看它們是如何解決訓練過程中的類別不平衡問題的。
one-stage檢測器
Faster R-CNN 中有一個專用的候選區域網絡RPN。基于區域的檢測器是很準確的,但需要付出代價。Faster R-CNN 在 PASCAL VOC 2007 測試集上每秒處理 7 幀的圖像(7 FPS)。作為替代,我們是否需要一個分離的候選區域步驟?我們可以直接在一個步驟內得到邊界框和類別嗎?
feature_maps = process(image)
results = detector3(feature_maps) # No more separate step for ROIs
讓我們再看一下滑動窗口檢測器。我們可以通過在特征圖上滑動窗口來檢測目標。對于不同的目標類型,我們使用不同的窗口類型。以前的滑動窗口方法的致命錯誤在于使用窗口作為最終的邊界框,這就需要非常多的形狀來覆蓋大部分目標。更有效的方法是將窗口當做初始猜想,這樣我們就得到了從當前滑動窗口同時預測類別和邊界框的檢測器。
這個概念和 Faster R-CNN 中的錨點很相似。然而,單次檢測器會同時預測邊界框和類別。例如,我們有一個 8 × 8 特征圖,在每個位置,我們有 k 個錨點(錨點是固定的初始邊界框猜想),一個錨點對應一個特定位置。我們使用相同的錨點形狀仔細地選擇錨點和每個位置,并在每個位置做出 k 個預測,即總共有 8 × 8 × k 個預測結果。
以下是 4 個錨點(綠色)和 4 個對應預測(藍色),每個預測對應一個特定錨點。
在 Faster R-CNN 中,我們使用卷積核來做 6個參數的預測:4 個參數對應某個錨點的預測邊框,2個參數對應 objectness 置信度得分。因此 3× 3× D × 6 卷積核將特征圖從 8 × 8 × D 轉換為 8 × 8 × 6。
在單次檢測器中,卷積核還預測 C 個類別概率以執行分類(每個概率對應一個類別,包含背景)。因此我們應用一個 3× 3× D × 25 卷積核將特征圖從 8 × 8 × D 轉換為 8 × 8 × 25 (C=20,(dx, dy, dh, dw, confidence)4個邊框參數,1個置信度)。
單次檢測器通常需要在準確率和實時處理速度之間進行權衡。它們在檢測太近距離或太小的目標時容易出現問題。在下圖中,左下角有 9 個圣誕老人,但某個單次檢測器只檢測出了 5 個。
2.1 SSD
SSD(Single-Shot MultiBox Detector),使用 VGG19 網絡作為特征提取器(和 Faster R-CNN 中使用的 CNN 一樣)的單次檢測器。我們在該網絡之后添加自定義卷積層(藍色),并使用卷積核(綠色)執行預測。
然而,卷積層降低了空間維度和分辨率。因此上述模型僅可以檢測較大的目標。為了解決該問題,我們從多個特征圖上執行獨立的目標檢測。
以下是特征圖圖示。
SSD 使用卷積網絡中較深的層來檢測目標。如果我們按接近真實的比例重繪上圖,我們會發現圖像的空間分辨率已經被顯著降低,且可能已無法定位在低分辨率中難以檢測的小目標。如果出現了這樣的問題,我們需要增加輸入圖像的分辨率。
2.2 YOLO / v2 / v3
YOLO (You Only Look Once)是另一種單次目標檢測器。YOLO 在卷積層之后使用了 DarkNet 來做特征檢測。
然而,它并沒有使用多尺度特征圖來做獨立的檢測。相反,它將特征圖部分平滑化,并將其和另一個較低分辨率的特征圖拼接。例如,YOLO 將一個 28 × 28 × 512 的層重塑為 14 × 14 × 2048,然后將它和 14 × 14 ×1024 的特征圖拼接。之后,YOLO 在新的 14 × 14 × 3072 層上應用卷積核進行預測。
YOLO v2做出了很多實現上的改進,比如使用BN層、使用高分辨率圖像微調分類模型、采用Anchor Boxes、約束預測邊框的位置等,將 mAP 值從第一次發布時的 63.4 提高到了 78.6。YOLO9000 可以檢測 9000 種不同類別的目標。
YOLO v3主要的改進有:調整了網絡結構;利用多尺度特征進行對象檢測;對象分類用logistic取代了softmax。下面主要介紹一下YOLO v3。(參考文章:YOLO v3深入理解)
網絡架構
在基本的圖像特征提取方面,YOLO v3采用了稱之為Darknet-53的網絡結構(含有52個卷積層1個全連接層),它借鑒了殘差網絡residual network的做法,在一些層之間設置了快捷鏈路(shortcut connections)。DarkNet-53 主要由 3 × 3 和 1× 1 的卷積核以及類似 ResNet 中的快捷鏈路構成。相比 ResNet-152,DarkNet 有更低的 BFLOP(十億次浮點數運算),但能以 2 倍的速度得到相同的分類準確率。
上圖的Darknet-53網絡采用2562563作為輸入,最左側那一列的1、2、8等數字表示多少個重復的殘差組件。每個殘差組件有兩個卷積層和一個快捷鏈路,示意圖如下:
特征金字塔網絡(FPN)——利用多尺度特征進行檢測
YOLO v2曾采用passthrough結構來檢測細粒度特征,在YOLO v3更進一步采用了3個不同尺度的特征圖來進行對象檢測。
結合上圖看,卷積網絡在79層后,經過下方幾個黃色的卷積層得到一種尺度的檢測結果。相比輸入圖像,這里用于檢測的特征圖有32倍的下采樣。比如輸入是416x416的話,這里的特征圖就是13x13了。由于下采樣倍數高,這里特征圖的感受野比較大,因此適合檢測圖像中尺寸比較大的對象。
為了實現細粒度的檢測,第79層的特征圖又開始作上采樣(從79層往右開始上采樣卷積),然后與第61層特征圖融合(Concatenation),這樣得到第91層較細粒度的特征圖,同樣經過幾個卷積層后得到相對輸入圖像16倍下采樣的特征圖。它具有中等尺度的感受野,適合檢測中等尺度的對象。
最后,第91層特征圖再次上采樣,并與第36層特征圖融合,最后得到相對輸入圖像8倍下采樣的特征圖。它的感受野最小,適合檢測小尺寸的對象。
上面使用不同尺寸特征圖進行預測的網絡稱為特征金字塔網絡(FPN),是一種旨在提高準確率和速度的特征提取器。數據流如下:
FPN 由自下而上和自上而下路徑組成。其中自下而上的路徑是用于特征提取的常用卷積網絡。空間分辨率自下而上地下降。當檢測到更高層的結構,每層的語義值增加。
SSD 通過多個特征圖完成檢測。但是,最底層不會被選擇執行目標檢測。它們的分辨率高但是語義值不夠,導致速度顯著下降而不能被使用。SSD 只使用較上層執行目標檢測,因此對于小的物體的檢測性能較差。
FPN 提供了一條自上而下的路徑,從語義豐富的層利用上采樣構建高分辨率的層。
雖然該重建層的語義較強,但在經過所有的上采樣和下采樣之后,目標的位置不精確。在重建層和相應的特征圖之間添加橫向連接可以使位置偵測更加準確。
FPN 可以結合 Fast R-CNN 或 Faster R-CNN。在 FPN 中,我們生成了一個特征圖的金字塔,然后用 RPN(來生成 ROI。基于 ROI 的大小,我們選擇最合適尺寸的特征圖層來提取特征塊。
9種尺度的 anchor boxes
隨著輸出的特征圖的數量和尺度的變化,先驗框的尺寸也需要相應的調整。YOLO2已經開始采用K-means聚類得到先驗框的尺寸,YOLO3延續了這種方法,為每種下采樣尺度設定3種先驗框,總共聚類出9種尺寸的先驗框。在COCO數據集這9個先驗框是:(10x13),(16x30),(33x23),(30x61),(62x45),(59x119),(116x90),(156x198),(373x326)。
分配上,在最小的13x13特征圖上(有最大的感受野)應用較大的先驗框(116x90),(156x198),(373x326),適合檢測較大的對象。中等的26x26特征圖上(中等感受野)應用中等的先驗框(30x61),(62x45),(59x119),適合檢測中等大小的對象。較大的52x52特征圖上(較小的感受野)應用較小的先驗框(10x13),(16x30),(33x23),適合檢測較小的對象。
感受一下9種先驗框的尺寸,下圖中藍色框為聚類得到的先驗框。黃色框式ground truth,紅框是對象中心點所在的網格。
分類softmax改成logistic
預測對象類別時不使用softmax,改成使用logistic的輸出進行預測。
輸入映射到輸出
不考慮神經網絡結構細節的話,總的來說,對于一個輸入圖像,YOLO v3將其映射到3個尺度的輸出張量,代表圖像各個位置存在各種對象的概率。
我們看一下YOLO v3共進行了多少個預測。對于一個416x416的輸入圖像,在每個尺度的特征圖的每個網格設置3個先驗框,總共有 13x13x3 + 26x26x3 + 52x52x3 = 10647 個預測。每一個預測是一個(4+1+80)=85維向量,這個85維向量包含邊框坐標(4個數值),邊框置信度(1個數值),對象類別的概率(對于COCO數據集,有80種對象)。
對比一下,YOLO v2采用13x13x5 = 845個預測,YOLO v3的嘗試預測邊框數量增加了10多倍,而且是在不同分辨率上進行,所以mAP以及對小物體的檢測效果有一定的提升。
2.3 RetianNet
RetianNet是基于 ResNet、FPN以及利用 Focal loss 構建的 。
Focal Loss
類別不平衡會損害性能。SSD 在訓練期間重新采樣目標類和背景類的比率,這樣它就不會被圖像背景淹沒。Focal loss(FL)采用另一種方法來減少訓練良好的類的損失。因此,只要該模型能夠很好地檢測背景,就可以減少其損失并重新增強對目標類的訓練。我們從交叉熵損失 (Cross Entroy Loss)開始,并添加一個權重來降低高可信度類的交叉熵。
例如,令 γ = 0.5, 經良好分類的樣本的 Focal Loss 趨近于 0。