1. 程式人生 > >物體檢測Object Detection學習筆記(MXNet)(二)

物體檢測Object Detection學習筆記(MXNet)(二)

錨框生成過多的問題

  上一節學習到,我們是基於生成的錨框來預測物體類別和偏移量,而且我們對於一張原始圖片,對於每個畫素都會生成多個錨框。
  問題:我們生成了大量的錨框,而在其中有大量的重複區域,造成了運算量過於複雜。那麼如何減少我們的計算量呢?
  其實很簡單,我們只需要對原始影象均勻取樣一小部分畫素,並以取樣的畫素為中心生成錨框,這樣我們可以通過控制取樣的畫素個數,而控制整體的運算複雜度。

尺度

  尺度這個概念其實在生活中我們常常接觸,舉一些比較形象的例子,比如說我們用手機拍照時,可以通過縮小放大畫面,從而改變尺度。我們在用地圖的時候,也可以縮小和放大改變尺度。
  計算機在不知道我們感興趣的物體尺寸情況下,我們就需要考慮多尺度以獲得感興趣物體的最佳尺度。
  具體一點到我們的CNN中,我們CNN中一般越靠近輸出層的特徵圖高和寬會越來越小,我們可以看做是,在越靠近輸出層的特徵圖每個畫素感受野越大

,也就是說每個畫素能反映原圖片中越大的區域,也就是尺度越大。(比如在靠近輸入層地方的特徵圖,一個畫素只能對應原影象中3*3的畫素區域,但是在靠近輸出層地方的特徵圖,一個畫素有可能就對應30*30的畫素區域)
  目標檢測過程中,較小目標相比於較大目標在影象上出現的位置可能性更多,比如形狀為11,21,221*1,2*1,2*2的目標在形狀為222*2的影象區域上出現的位置可能性為4,2,14,2,1種。所以我們可以在靠近輸出層的大尺度特徵圖中生成大小比例大、數量較少的錨框,來檢測尺寸比較大的物體。在前面的一些小尺寸特徵圖中生成大小比例小、數量較多的錨框,來檢測尺寸較小的物體。

如何在MXNet中生成多尺度的錨框

  問題來了,我們如何用MXNet中函式生成多尺度的錨框呢?其實很簡單,我們直接使用不同大小的特徵圖作為輸入,然後生成錨框,最後還原的時候乘以原始影象的寬和高就OK了。也就是我們可以通過定義一個特徵圖來對整個原始影象均勻取樣。
  我們知道生成錨框的函式為contrib.nd.MultiBoxPrior,這個函式的輸出為(1,錨框總數,4)其中各個不同的批量共享這些錨框。這個函式輸出的四個座標自動的除以了輸入的寬和高,歸一化到了0和1之間。這就代表了輸出的錨框是相對於整個影象的相對位置,由於我們生成錨框是對特徵圖每個畫素都生成,所以我們基於這個特徵圖生成的錨框一定是對原始影象均勻取樣得到的。

def show_diff_scale_anchors(axes,fmap_w,fmap_h,sizes,ratios,img_scale):
    #顯示不同尺度的影象
    fmap = nd.zeros(shape=(1,3,fmap_h,fmap_w))
    #生成錨框 
    anchors = contrib.nd.MultiBoxPrior(fmap,sizes=sizes,ratios=ratios)
    #顯示多尺度
    show_all_bboxes(axes,anchors[0]*img_scale)
    
plt.figure(figsize=(7,7))
img = image.imread('../img/catdog.jpg').asnumpy()
fig = plt.imshow(img)
show_diff_scale_anchors(fig.axes,4,4,[0.15],[1,2,0.5],img_scale)

  上面我們在444*4的特徵圖上生成錨框,一共取樣了16個畫素,每個畫素有3個錨框,結果如下:

在這裡插入圖片描述

  接下來我們嘗試加大尺度,在222*2的特徵圖上生成錨框,此時我們的錨框大小比例應該加大,而個數應該減小,結果如下:

plt.figure(figsize=(7,7))
img = image.imread('../img/catdog.jpg').asnumpy()
fig = plt.imshow(img)
show_diff_scale_anchors(fig.axes,2,2,[0.3],[0.7,0.5],img_scale)

在這裡插入圖片描述

  最後我們嘗試最大的尺度,使用111*1的特徵圖,此時我們應該是在中心畫素生成錨框,結果如下:

plt.figure(figsize=(7,7))
img = image.imread('../img/catdog.jpg').asnumpy()
fig = plt.imshow(img)
show_diff_scale_anchors(fig.axes,1,1,[0.75],[0.7,0.5],img_scale)

在這裡插入圖片描述

總結

  1. 不同尺度的特徵圖在原始輸入影象中含有不同的感受野,越靠近輸出層的特徵圖每個畫素的感受野越大,越適合用來檢測大物體
  2. 我們可以使用contrib.nd.MultiBoxPrior函式很方便生成不同尺度的錨框,最後我們還原時乘以輸入影象的高和寬就行
  3. SSD就是一種多尺度的目標檢測框架