目標檢測,即在一幅圖里框出某個目標位置.有2個任務.
- 定位出目標的邊界框
- 識別出邊界框內的物體的類別
Sliding-window detectors
一種暴力的目標檢測方法就是使用滑動窗口,從左到右,從上到下掃描圖片,然后用分類器識別窗口中的目標.為了檢測出不同的目標,或者同一目標但大小不同,必須使用不同大小,不同寬高比的滑動窗口.
把滑動窗口框出來的圖片塊resize(因為很多分類器只接受固定大小的圖片輸入)后,送給CNN分類器,CNN提取出4096個特征.然后使用SVM做分類,用線性回歸做bounding box預測.
偽代碼如下
for window in windows
patch = get_patch(image, window)
results = detector(patch)
提高性能的一個明顯的方法就是減少window數量.
Selective Search
相比於暴力搜索,我們使用一種區域建議(region proposal)方法去創建roi(感興趣區域region of intrest).在selective search(SS)中,我們從將每一個像素作為一個group開始,接下來我們計算每一個group的texture,然后合並最接近的group.為例避免某個區域吞並了其他區域,我們優先合並較小的group,不斷的合並各個group直到不能再合並了.如下圖:第一行圖顯示了region是怎么不斷地增長的,第二行的藍色框顯示了在不斷地合並的過程里,是怎么產生ROI的.
R-CNN
R-CNN采取區域建議方法創建2000個ROI.然后這些區域的圖片被送到CNN,提取特征,然后送給全連接層做邊界框預測和類別預測
流程如下:
由於有了數量少質量高的ROI,R-CNN相比於暴力的滑動窗口搜索,要快的多,也准確的多.
ROIs = region_proposal(image)
for ROI in ROIs
patch = get_patch(image, ROI)
results = detector(patch)
Boundary box regressor
區域建議方法是需要大量算力的.為了加速ROI尋找的過程,我們往往選擇一個不需要巨量算力的區域建議方法來創建ROI,再用線性回歸器(使用全連接層)對邊界框做微調.
Fast R-CNN
R-CNN需要大量的ROI,並且這些ROI很多都是重疊的.所以R-CNN在無論是訓練還是推理都很慢.如果我們有2000個建議區域,每一個都要被CNN處理一次,也就是說,對於不同的ROI,特征提取重復了2000次.
換個思路,對整幅圖片做特征提取,然后在特征圖的基礎上做ROI的查找.通過池化層做resize,然后送給全連接層做邊界框預測和分類.由於只做了一次特征提取,Fast R-CNN的性能顯著提高.
流程如下:
偽代碼如下:
feature_maps = process(image)
ROIs = region_proposal(image)
for ROI in ROIs
patch = roi_pooling(feature_maps, ROI)
results = detector2(patch)
由於把特征提取這一步抽到了for循環外部,性能大幅提升.相比R-CNN,Fast R-CNN在訓練上快了10倍,推理上快了150倍.
Fast R-CNN的一個要點是整個網絡(包括特征提取,分類,邊界框回歸)是端到端的訓練,並且采用了multi-task losses(分類loss + 邊界框定位loss),提高了准確率.
ROI pooling
由於Fast R-CNN使用全連接層,我們采用ROI池化,把不同size的ROI轉換成固定size.
以8*8的特征圖轉換為2*2為例
- 左上:CNN得到的原始特征圖
- 右上:疊加藍色的ROI到特征圖上
- 左下:將ROI分割成目標維度.比如要轉換成2*2的,那我們把ROI分成4份,每一份大小近似.
- 右下:對每一份做max pooling(即選出該部分最大的).得到我們想要的ROI對應的特征圖.
然后就可以把這些2*2的特征圖送給分類器和線性回歸器去做分類和邊界框預測了.
Faster R-CNN
Fast R-CNN依賴於區域建議方法,比如selective search.但是,這些算法只能跑在cpu上,速度很慢.在測試中,Fast R-CNN做出一次預測要2.3秒,其中2秒都花在了生成2000個ROI.
feature_maps = process(image)
ROIs = region_proposal(image) # Expensive!
for ROI in ROIs
patch = roi_pooling(feature_maps, ROI)
results = detector2(patch)
在流程上,Faster R-CNN與Fast R-CNN是一致的,只是將得到ROI的方式改為由一個region proposal network(RPN)得到.RPN效率要高的多,每張圖生成ROI的時間僅在10ms.
Region proposal network
RPN接受卷積網絡輸出的特征圖作為輸入,用如下的ZF網絡做區域建議.也可以用其他的網絡比如VGG或者ResNet去做更全面的特征提取,代價是速度的下降.ZF網絡輸出256個值,送到兩個全連接層,一個用於預測邊界框(boudary box),一個用於預測2個objectness scores.objectness衡量bounding box是否包含一個object.我們可以用一個回歸器去計算出一個single objectness score.但是為簡單起見,Fast R-CNN使用一個分類器,分類器分出的類別有2種:即包含目標和不包含.
對特征圖中的每一個位置,RPN做出k個猜測.所以RPN輸出4*k個坐標,2*k個score.如下表示對一個8*8的特征圖,用3*3的filter,最終得到8*8*3個ROI.
后面我們將繼續微調我們的猜測.由於我們需要有一個正確的猜測,我們初始化的猜測最好有不同的shape,不同的size.所以,Faster R-CNN不是隨機亂猜的邊界框,它預測相對於我們稱之為anchors的參考框(reference box)左上角的偏移.我們限定偏移的大小,這樣我們最終預測出的bounding box依然是與anchors類似的.
為了每個位置能夠得到k個預測,每個位置需要k個anchor.每一個預測都與一個特定的anchor有關.不同的位置共享同樣的anchor shape.
這些anchors不是瞎選的,要盡可能地覆蓋到real-life objects,並且要盡量有合理的尺度和寬高比.這樣可以使得每次的prediction更准確.這個策略使得訓練的早期可以更容易更穩定.
Faster R-CNN uses far more anchors. It deploys 9 anchor boxes: 3 different scales at 3 different aspect ratio. Using 9 anchors per location, it generates 2 × 9 objectness scores and 4 × 9 coordinates per location.
Performance for R-CNN methods
Region-base Fully Convolutional Networks (R-FCN)
假設一下我們只有一個檢測臉部中右眼的feature map,我們可以用它來定位整張臉嗎?答案是肯定的,因為右眼位於面部的左上角,所以我們可以用來定位整張臉.
如果我們有其他專門用於檢測左眼、鼻子或嘴巴的特征圖,我們可以將這些結果結合起來,更好地定位人臉.
在Faster R-CNN中,我們最終會將整幅圖片的feature map切成相應的roi對應的feature map,再送給多個全連接層去做預測.有2000個ROI的時候,這一步的代價是很高昂的.
feature_maps = process(image)
ROIs = region_proposal(feature_maps)
for ROI in ROIs
patch = roi_pooling(feature_maps, ROI)
class_scores, box = detector(patch) # Expensive!
class_probabilities = softmax(class_scores)
R-FCN通過減少每一個roi的處理時間提速.下面是偽代碼
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)
考慮一個5*5的feature map,其中藍色部分的feature構成了我們想要檢測的object.我們將藍色部分划分為3*3的區域.現在我們可以創建一個新的feature map,僅僅用來檢測object的top left corner(TL).如下:
由於我們將object分成了9個部分,我們從整幅圖的feature map中得到9個feature map,每一個feature map負責檢測object的相應區域.這些feature map我們稱之為position-sensitive score maps,因為每個map都只detect(scores)一個object的子區域.
假設下圖的紅色虛線框是ROI.我們將其划分成3*3的區域,然后考慮每個區域包含目標的對應位置的可能性.例如,top-left ROI區域包含左眼的可能.我們把結果存儲在一個3*3的vote array里.比如,vote_array[0][0]存儲了一個score,表示我們是否發現了目標的top-left region.
這個依據score map和ROI得到vote array的過程稱之為position-sensitive ROI-pool.這個過程和前文提過的ROI pool很類似.
計算出所有的值以后,取平均,就得到了class score.
假設我們有C種目標待檢測.我們擴展為C+1種,即包含一種class for the background(non-object).每一種目標都有自己的3*3個score map.所以一共有(C+1)*3*3個score maps.使用這些score maps我們可以為每一個類別都算出一個class score.然后用softmax可以計算出每一個類別的class probability.
整體流程如下,下圖中k=3.
R-FCN的一個示例