天天看點

SSD小記(一) SSD怎樣在特征圖上放置anchor

一、SSD中anchor_sizes是如何得到的

default_params = SSDParams(
        img_shape=(300, 300),
        num_classes=21,
        no_annotation_label=21,
        feat_layers=['block4', 'block7', 'block8', 'block9', 'block10', 'block11'],
        feat_shapes=[(38, 38), (19, 19), (10, 10), (5, 5), (3, 3), (1, 1)],
        anchor_size_bounds=[0.15, 0.90],
        # anchor_size_bounds=[0.20, 0.90],
        anchor_sizes=[(21., 45.),
                      (45., 99.),
                      (99., 153.),
                      (153., 207.),
                      (207., 261.),
                      (261., 315.)],
        # anchor_sizes=[(30., 60.),
        #               (60., 111.),
        #               (111., 162.),
        #               (162., 213.),
        #               (213., 264.),
        #               (264., 315.)],
        anchor_ratios=[[2, .5],
                       [2, .5, 3, 1./3],
                       [2, .5, 3, 1./3],
                       [2, .5, 3, 1./3],
                       [2, .5],
                       [2, .5]],
        anchor_steps=[8, 16, 32, 64, 100, 300],
        anchor_offset=0.5,
        normalizations=[20, -1, -1, -1, -1, -1],
        prior_scaling=[0.1, 0.1, 0.2, 0.2]
        )
           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

其中這個

anchor_sizes

是最magic的一組數字,他到底是怎麼來的呢?

首先你要知道這個公式:

SSD小記(一) SSD怎樣在特征圖上放置anchor

Sk是每個特征層的先驗框大小與原圖檔大小之比,Smax和Smin分别是最大,最小的比例.

在SSD中一共有6個用于分類和回歸的特征層(feature map),

分别是

feat_layers=['block4', 'block7', 'block8', 'block9', 'block10', 'block11'],

m

是就是特征層的個數,按理說分母應該是6-1=5,但是這裡是5-1=4, 因為作者将第一層S1, 單獨拿出來設定了.

k

是第幾個特征層的意思,注意k的範圍是1~m, 也就是1~6.

知道這些就可以開始計算了.

Sk在實際計算中考慮到取整的問題,所有與上式有所差別:

SSD小記(一) SSD怎樣在特征圖上放置anchor

需要向下取整.

是以你将m=5, Smin, Smax=(0.2, 0.9) 就是

anchor_size_bounds=[0.20, 0.90],

帶入之後,

得到S1~S6: 20, 37, 54, 71, 88, 105, 其實就是挨個+17.

此時你還需要将其除以100還原回來,也就是:

0.2, 0.37, 0.54, 0.71, 0.88, 1.05

然後,我們這個是比例, 我們需要得到其在原圖上的尺寸,是以需要依次乘以300, 得到:

60, 111, 162, 213, 264, 315.

最後,你會問: 30呢? 這就要說到S1’了,S1’=0.5*S1, 就是0.1, 再乘以300, 就是30.

這樣, 我們有七個數, 6個區間段, 也就是6組min_size和max_size. 就可以計算每個特征層的anchor_box 的尺寸了.詳細見下片博文.

可以看出作者為了不讓我們搞懂他的代碼,也是煞費苦心啊…

最後, 既然我們高明白了anchor_size, 這個參數直接決定了目前特征層的box 的大小, 可以看出越靠近輸入層, box越小, 越靠近輸出層, box越大, 是以 SSD的底層用于檢測小目标, 高層用于檢測大目标.

二、SSD的anchor_box計算

看過SSD的tensorflow實作的小夥伴一定對anchor_box的計算很是好奇, 網上也是五花八門的解釋,今天我結合源碼和原理來解釋一下.

default_params = SSDParams(
        img_shape=(300, 300),
        num_classes=21,
        no_annotation_label=21,
        feat_layers=['block4', 'block7', 'block8', 'block9', 'block10', 'block11'],
        feat_shapes=[(38, 38), (19, 19), (10, 10), (5, 5), (3, 3), (1, 1)],
        anchor_size_bounds=[0.15, 0.90],
        # anchor_size_bounds=[0.20, 0.90],
        anchor_sizes=[(21., 45.),
                      (45., 99.),
                      (99., 153.),
                      (153., 207.),
                      (207., 261.),
                      (261., 315.)],
        # anchor_sizes=[(30., 60.),
        #               (60., 111.),
        #               (111., 162.),
        #               (162., 213.),
        #               (213., 264.),
        #               (264., 315.)],
        anchor_ratios=[[2, .5],
                       [2, .5, 3, 1./3],
                       [2, .5, 3, 1./3],
                       [2, .5, 3, 1./3],
                       [2, .5],
                       [2, .5]],
        anchor_steps=[8, 16, 32, 64, 100, 300],
        anchor_offset=0.5,
        normalizations=[20, -1, -1, -1, -1, -1],
        prior_scaling=[0.1, 0.1, 0.2, 0.2]
        )
           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

這個anchor_box的計算與anchor_sizes和anchor_ratios有關.

先解釋一下anchor_box的由來. 我們假設目前層是block4, 那麼我們的feat_shape就是(38, 38),

你可以将其了解為38*38個cell單元, 每個單元要預測出來幾個anchor_box, 不同的層, 這個數理論上講都是6個, (paper上就是這麼寫的). 每個box的長寬比是有ratios決定的, paper上是兩個 1 , 以及4個其他的值. 但是作者的源碼卻很調皮的改了一下.

看一下我們的長寬比,這裡面沒有那兩個1, 因為他們是單獨設定的:

anchor_ratios=[[2, .5],
               [2, .5, 3, 1./3],
               [2, .5, 3, 1./3],
               [2, .5, 3, 1./3],
               [2, .5],
               [2, .5]],
           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

我們看到第一層還有最後兩層, 隻有兩種長寬比, 是以這三層就隻有4種box.

SSD小記(一) SSD怎樣在特征圖上放置anchor

這個圖可以說介紹的相當準确定了, 網上有錯的, 以這個為準 . 以block4層為例, 他每個cell單元隻有4個box, 包括一大一小兩個正方形, 以及兩個長方形.

對于小正方形,其邊長為min_size, 這個min_size是什麼呢?就是前面參數中的anchor_sizes:

anchor_sizes=[(30., 60.),
   			(60., 111.),
   			(111., 162.),
   			(162., 213.),
   			(213., 264.),
   			(264., 315.)],
           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

其中每一行為一組, 每一行對應相應的特征層, 第一行對應的就是block4, 依次類推, 對于(30, 60), 30就是min_size, 60就是max_size.

大正方形其邊長為

SSD小記(一) SSD怎樣在特征圖上放置anchor

然後是另外兩個長方形,這個時候anchor_ratios就出馬了,長方形的長寬是有公式可尋的.

SSD小記(一) SSD怎樣在特征圖上放置anchor

這個ratio就是anchor_ratios裡的2, 5, 3, 1/3 之類的.

這樣,原理上box的大小就介紹完了.但是别忘了這個尺寸是在原圖上的尺寸, 我們需要這個尺寸相對于原圖的比例.

看下源碼的這一部分:

# Add first anchor boxes with ratio=1.
	# sizes就是(30, 60), img_shape就是原圖尺寸(300, 300)
    h[0] = sizes[0] / img_shape[0]
    w[0] = sizes[0] / img_shape[1]
    di = 1
    if len(sizes) > 1:
        h[1] = math.sqrt(sizes[0] * sizes[1]) / img_shape[0]
        w[1] = math.sqrt(sizes[0] * sizes[1]) / img_shape[1]+= 1 # r 就是[2, 5, 3, 1/3]    
    for i, r in enumerate(ratios):
        h[i+di] = sizes[0] / img_shape[0] / math.sqrt(r)
        w[i+di] = sizes[0] / img_shape[1] * math.sqrt(r)
           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

最後, 既然我們高明白了anchor_size, 這個參數直接決定了目前特征層的box 的大小, 可以看出越靠近輸入層, box越小, 越靠近輸出層, box越大, 是以 SSD的底層用于檢測小目标, 高層用于檢測大目标.

三、SSD中feat_shapes與anchor_steps的對應問題

feat_shapes=[(38, 38), (19, 19), (10, 10), (5, 5), (3, 3), (1, 1)]
anchor_steps=[8, 16, 32, 64, 100, 300],
           
  • 1
  • 2

按理說anchor_step * feat_shape 應該全部等于300的呀, 可為什麼不是呢? 這就涉及到向上取整的問題了.300/38 = 7.89 那就是8, 300/19 = 15.789 那就是16, 以此類推. 這個問題就明白了.

轉載于部落格: https://blog.csdn.net/qq_36735489/article/details/83654900,如有需要請從原文出處轉載;

繼續閱讀