1. 程式人生 > >基於區域的目標檢測

基於區域的目標檢測

目標檢測,即在一幅圖裡框出某個目標位置.有2個任務.

  • 定位出目標的邊界框
  • 識別出邊界框內的物體的類別

Sliding-window detectors

一種暴力的目標檢測方法就是使用滑動視窗,從左到右,從上到下掃描圖片,然後用分類器識別視窗中的目標.為了檢測出不同的目標,或者同一目標但大小不同,必須使用不同大小,不同寬高比的滑動視窗.

把滑動視窗框出來的圖片塊resize(因為很多分類器只接受固定大小的圖片輸入)後,送給CNN分類器,CNN提取出4096個特徵.然後使用SVM做分類,用線性迴歸做bounding box預測.


虛擬碼如下

for window in windows
    patch = get_patch(image, window)
    results = detector(patch)

提高效能的一個明顯的方法就是減少window數量.

相比於暴力搜尋,我們使用一種區域建議(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的一個示例

原文link:https://medium.com/@jonathan_hui/what-do-we-learn-from-region-based-object-detectors-faster-r-cnn-r-fcn-fpn-7e354377a