其實出發點我覺得不難想到,主要基於以下幾點設計出來了SSD的結構:
這張圖能把我說的第2,3點講清楚了。
原圖(a)中有一個較小的目標(籃框),和一個較大的目標(紅框)。
原圖經過多層卷積後,可以在某層上得到8x8的feature map,即圖(b),也可以在稍後面的層得到4x4的feature map,即圖(c)。
針對圖(b),每個位置上出4(或6)個,圖中是出4個不同scale和aspect ratio的anchors。比如ratio_anchor=2x2,也就是在8x8和4x4兩種feature map上anchor size是相同的,都是2x2,那麼由於8x8層對應的感受野比4x4的小,因此2x2的anchor對應到原圖上則是較小的一塊區域。那麼,原圖中較大的目標(紅框表示的物體)在8x8 feature map很可能沒有anchor能檢測到它,但藍框物體是可以在8x8 feature map上檢測到的,即圖(b)中的2個藍虛線框所表示的anchors。對應的,4x4 feature map的感受野更大,它上面就可能有對應的anchor能檢測到原圖中較大物體,即圖(c)中的紅虛線框所表示的anchor。這樣一來,原圖中一大一小兩個物體就在不同scale的feature map上被檢測出來了。
這就是為什麼SSD要利用「直筒」網路的不同scale的feature maps,每個都出classifier head和regression head來做檢測的原因。
原文中的圖例使用的是VGG。
先看原始的VGG網路結構,如下圖:
作為SSD的backbone時,只用到了conv5以前的層。pool5開始到後面幾個FC層都去掉了。
去掉原始的一些層之後,作者又加入了新層,如下圖所示。
conv5-3之後的三層:pool5,conv6和conv7都是新增的。這裡pool5的stride=1並沒有做downsampling,保持了conv5-3的output size。
按論文中作者設定的輸入圖片大小為(B,3,300,300),那麼conv5-3之後得到(B,512,19,19),pool5後仍然為(B,512,19,19)。
pool5後接了一個3x3帶dilation的卷積層conv6,又接一個1x1的conv7。這兩層的輸出都相同,為(B,1024,19,19)。
這些層為了逐步得到multi scale的feature而存在。具體請看下圖:
從conv8到conv11共四層,出4種不同scale的feature map。
conv8-1的輸入也就是conv7的輸出,shape=[B,1024,19,19]
-------------------------------------------------------------------------------------------
經過conv8-1,ksize=1,filter num=256,輸出[B,256,19,19](1x1降低channel數)
經過conv8-2,ksize=3,filter num=512,stride=2,padding=1,輸出[B,512,10,10]
經過conv9-1,ksize=1,filter num=128,輸出[B,128,10,10] (1x1降低channel數)
經過conv9-2,ksize=3,filter num=256,stride=2,padding=1,輸出[B,256,5,5]
經過conv10-1,ksize=1,filter num=128,輸出[B,128,5,5]
經過conv10-2,ksize=3,filter num=256,stride=1,輸出[B,256,3,3]
經過conv11-1,ksize=1,filter num=128,輸出[B,128,3,3]
經過conv11-2,ksize=3,filter num=256,stride=1,輸出[B,256,1,1]
以上就得到了extra feature layers,對應於原論文中圖例的結構。
從上一步得到[B,512,10,10],[B,256,5,5],[B,256,3,3],[B,256,1,1]四種feature map,再加上conv4-3[B,512,38,38]和conv7[B,1024,19,19]兩層較淺的特徵(為了檢測小目標)。
這六個feature map,每個位置上都要出4或6個anchors,每個anchor要輸出n_classes個prob(cls_head),和4個bbox偏移量(reg_head)。
假如anchor_num=4, cls_head的卷積層out_channel=(anchor_num)x(n_classes),reg_head的卷積層out_channel=(anchor_num)x4。這些卷積的kernel size和padding都相同,ksize=3,padding=1。最終得到:
cls_head = [B, (anchor_num)x(n_classes), 38/19/10/5/3/1, 38/19/10/5/3/1]
reg_head = [B, (anchor_num)x4, 38/19/10/5/3/1, 38/19/10/5/3/1]
multi_box_cfg = [4,6,6,6,4,4],也就是這6個feature map上每個位置放置的anchor數不同的。有的層每個位置放4個anchor,有的feature map的每個位置放6個anchor。
那麼,總的detection bbox數=38x38x4+19x19x6+10x10x6+5x5x6+3x3x4+1x1x4=8732
https://github.com/amdegroot/ssd.pytorch/blob/master/ssd.py?github.com 推薦閱讀: