SSD300默認框尺寸計算

目錄

1. 計算特徵圖的min_size與max_size

2. 計算特徵圖的默認框尺寸

3. 測試


1. 計算特徵圖的min_size與max_size

先將SSD300網絡模型附上,如圖:

SSD300是因爲該網絡的輸入尺寸是300x300,所以別名是SSD300,從SSD網絡模型與原文中知道,有6個feature_map層,分別是[conv4_3, fc7, conv8_2, conv9_2, conv10_2, conv11_2],但是我們在代碼中一般不會這樣起名,而是[conv4_3, fc7, conv6_2, conv7_2, conv8_2, conv9_2] ,這些都是小問題,不用太在乎。

從原文中,我們知道有6個feature map 層,每層的默認框數量如下:

每層默認框數量
conv4_3 4
fc7 6
conv6_2 6
conv7_2 6
conv8_2 4
conv9_2 4

 

要求默認框的尺寸,要先求每層feature map的min_size 與 max_size,所以要求解6組min_size與max_size,代碼如下:

這個代碼好像是SSD作者寫的,我從別的地方借鑑的,然後修改了一點。

def compute_min_max_size(image_size=300):
    """
    :function: 計算SSD默認框的最小尺寸與最大尺寸
    :param image_size: 網絡輸入圖片最小尺寸,圖片儘量是正方形
    :return: 計算的最小尺寸與最大尺寸
    """
    min_dim = image_size  #######輸入圖片尺寸
    # conv4_3 ==> 38 x 38
    # fc7 ==> 19 x 19
    # conv6_2 ==> 10 x 10
    # conv7_2 ==> 5 x 5
    # conv8_2 ==> 3 x 3
    # conv9_2 ==> 1 x 1
    #####prior_box來源層,可以更改。很多改進都是基於此處的調整。
    mbox_source_layers = ['conv4_3', 'fc7', 'conv6_2', 'conv7_2', 'conv8_2', 'conv9_2']
    # in percent %
    ####這裏即是論文中所說的Smin=0.2,Smax=0.9的初始值,經過下面的運算即可得到min_sizes,max_sizes。具體如何計算以及兩者代表什麼,請關注我的博客SSD詳解。這裏產生很多改進。
    min_ratio = 20
    max_ratio = 90
    ####math.floor()函數表示:求一個最接近它的整數,它的值小於或等於這個浮點數。
    ####取一個間距步長,即在下面for循環給ratio取值時起一個間距作用。可以用一個具體的數值代替,這裏等於17。
    step = int(math.floor((max_ratio - min_ratio) / (
                len(mbox_source_layers) - 2)))
    min_sizes = []  ###經過以下運算得到min_sizes和max_sizes。
    max_sizes = []
    min_sizes = min_sizes + [min_dim * 10 / 100.]
    max_sizes = max_sizes + [min_dim * 20 / 100.]
    ####從min_ratio至max_ratio+1每隔step=17取一個值賦值給ratio。注意range函數的作用。
    for ratio in range(min_ratio, max_ratio + 1, step):
        ########min_sizes.append()函數即把括號內部每次得到的值依次給了min_sizes。
        min_sizes.append(min_dim * ratio / 100.)
        # print("min_size:", min_sizes)
        max_sizes.append(min_dim * (ratio + step) / 100.)
        # print("max_size:", max_sizes)

    return [min_sizes, max_sizes]

結合代碼講解,首先要曉得輸入圖片尺寸,SSD300的輸入尺寸是300x300,所以這裏的min_dim就是300啦。

mbox_source_layers這個變量作用不大,主要是爲了計算有幾個feature map層,我們已經知道有6個啦,這裏可能是爲了使代碼更高大上。

min_ratio 與 max_ratio就是論文中的Smin=0.2, Smax=0.9。

  至於爲什麼將min_ratio與max_ration置爲90,一是爲了計算step, 二是爲了後面間隔取值用的。 

step = int(math.floor((max_ratio - min_ratio) / (len(mbox_source_layers) - 2)))

step就是一個步長,使用range()函數,用於在min_ratio~max_ration之間取n個值,這裏n = 5,也正好符合我們的要求,爲什麼這樣說呢?feature map層不是有6層嗎?這是因爲第一層(conv4_3層)單獨計算,爲什麼這樣做,我也不曉得,可能有特別的用意,有曉得的同學,請在評論區評論,謝謝。

conv4_3層的min_size,max_size計算公式如下:

min_size = min_dim * 10 / 100.0

max_size = min_dim * 20 / 100.0 

這裏除以100.0的意思應該就是將增加100倍的ratio降低100倍,使其重歸於0.2~0.9 

剩下5層的計算公式如下:

min_size = min_dim * ratio / 100.0

max_size = min_dim * (ratio + step) / 100.0 

最終計算結果如下:

min_size:  [30.0, 60.0, 111.0, 162.0, 213.0, 264.0]
max_size:  [60.0, 111.0, 162.0, 213.0, 264.0, 315.0]
計算結果
  min_size max_size
conv4_3 30.0 60.0
fc7 60.0 111.0
conv6_2 111.0 162.0
conv7_2 162.0 213.0
conv8_2 213.0 264.0
conv9_2 264.0 315.0

2. 計算特徵圖的默認框尺寸

每個特徵層的min_size與max_size計算出來後,就可以計算每個特徵層的默認框尺寸啦。

aspect_ratios = [[2], [2, 3], [2, 3], [2, 3], [2], [2]]

這個是每個特徵層的長寬比,這裏並不是paper中所給出的ar={1,2,3,1/2,1/3},這個比例是計算出來的。

首先我們要知道,我們在前面也講了,每層的特徵圖的每個中心點分別會產生4、6、6、6、4、4個默認框,但我們要知道爲什麼是這幾個默認框,這裏就和aspect_ratios有關係了。

在SSD中6層卷積層的每個特徵圖的每個中心點會產生2個不同大小的正方形默認框,另外每設置一個aspect_ratio則會增加兩個長方形默認框,而文中代碼對於6層的aspect_ratio個數分別爲1、2、2、2、1、1,所以這也就是爲什麼會產生4、6、6、6、4、4個默認框了。例如conv4_3默認生成兩個不同大小的正方形默認框,另外又有一個aspect_ratio=2產生了兩個長方形默認框,所以總共有4個。再如fc7,默認生成兩個正方形默認框,另外又有aspect_ratio=[2,3],所以又生成了4個不同的長方形默認框,共有6個不同大小的默認框。
接着我們再講這些產生的默認框的大小計算。這裏參考paper中的計算公式,我們可以知道,對於產生的正方形的默認框,一大一小共兩個,其邊長計算公式爲:

小邊長=min_size

大邊長=sqrt(min_size*max_size)。

對於產生的長方形默認框,我們需要計算它的高(height)和寬(width),其中

height=1/sqrt(aspect_ratio)*min_size

width=sqrt(aspect_ratio)*min_size

對其高和寬翻轉後得到另一個面積相同但寬高相互置換的長方形。

具體代碼如下:

aspect_ratios = [[2], [2, 3], [2, 3], [2, 3], [2], [2]]
# mbox_source_layers = ['conv4_3', 'fc7', 'conv6_2', 'conv7_2', 'conv8_2', 'conv9_2']
def compute_default_box():
    min_sizes, max_sizes = compute_min_max_size()
    conv4_3 = np.zeros(shape=(4, 2))
    fc7 = np.zeros(shape=(6, 2))
    conv6_2 = np.zeros(shape=(6, 2))
    conv7_2 = np.zeros(shape=(6, 2))
    conv8_2 = np.zeros(shape=(4, 2))
    conv9_2 = np.zeros(shape=(4, 2))

    mbox_source_layers = [conv4_3, fc7, conv6_2, conv7_2, conv8_2, conv9_2]
    for i in range(6):
        # 每層feature中默認框的數量
        num = len(aspect_ratios[i]) * 2 + 2
        # for j in range(num):
        # 計算小正方形邊長  小邊長=min_size
        mbox_source_layers[i][0, :] = min_sizes[i]
        # 計算大正方形邊長  大邊長=sqrt(min_size*max_size)
        mbox_source_layers[i][1, :] = np.sqrt(min_sizes[i] * max_sizes[i])
        # 計算第一個長方形寬 width=sqrt(aspect_ratio)*min_size
        mbox_source_layers[i][2, 0] = np.sqrt(aspect_ratios[i][0]) * min_sizes[i]
        # 計算第一個長方形高 height=1/sqrt(aspect_ratio)*min_size
        mbox_source_layers[i][2, 1] = 1.0 / np.sqrt(aspect_ratios[i][0]) * min_sizes[i]
        # 計算第二個長方形寬 等於第一個長方形的高
        mbox_source_layers[i][3, 0] = mbox_source_layers[i][2, 1]
        # 計算第二個長方形高 等於第一個長方形的寬
        mbox_source_layers[i][3, 1] = mbox_source_layers[i][2, 0]
        # 判斷一哈是否要計算第三和第四個長方形
        if num == 6:
            # 計算第三個長方形的寬
            mbox_source_layers[i][4, 0] = np.sqrt(aspect_ratios[i][1]) * min_sizes[i]
            # 計算第三個長方形高
            mbox_source_layers[i][4, 1] = 1.0 / np.sqrt(aspect_ratios[i][1]) * min_sizes[i]
            # 計算第四個長方形寬 等於第三個長方形的高
            mbox_source_layers[i][5, 0] = mbox_source_layers[i][4, 1]
            # 計算第四個長方形高 等於第三個長方形的寬
            mbox_source_layers[i][5, 1] = mbox_source_layers[i][4, 0]

    return mbox_source_layers

3. 測試

完整代碼如下,運行即可,可根據需求,打印出想要的結果:

# -*- coding: utf-8 -*-
import math
import numpy as np

def compute_min_max_size(image_size=300):
    """
    :function: 計算SSD默認框的最小尺寸與最大尺寸
    :param image_size: 網絡輸入圖片最小尺寸,圖片儘量是正方形
    :return: 計算的最小尺寸與最大尺寸
    """
    min_dim = image_size  #######輸入圖片尺寸
    # conv4_3 ==> 38 x 38
    # fc7 ==> 19 x 19
    # conv6_2 ==> 10 x 10
    # conv7_2 ==> 5 x 5
    # conv8_2 ==> 3 x 3
    # conv9_2 ==> 1 x 1
    #####prior_box來源層,可以更改。很多改進都是基於此處的調整。
    mbox_source_layers = ['conv4_3', 'fc7', 'conv6_2', 'conv7_2', 'conv8_2', 'conv9_2']
    # in percent %
    ####這裏即是論文中所說的Smin=0.2,Smax=0.9的初始值,經過下面的運算即可得到min_sizes,max_sizes。具體如何計算以及兩者代表什麼,請關注我的博客SSD詳解。這裏產生很多改進。
    min_ratio = 20
    max_ratio = 90
    ####math.floor()函數表示:求一個最接近它的整數,它的值小於或等於這個浮點數。
    ####取一個間距步長,即在下面for循環給ratio取值時起一個間距作用。可以用一個具體的數值代替,這裏等於17。
    step = int(math.floor((max_ratio - min_ratio) / (
                len(mbox_source_layers) - 2)))
    min_sizes = []  ###經過以下運算得到min_sizes和max_sizes。
    max_sizes = []
    min_sizes = min_sizes + [min_dim * 10 / 100.]
    max_sizes = max_sizes + [min_dim * 20 / 100.]
    ####從min_ratio至max_ratio+1每隔step=17取一個值賦值給ratio。注意range函數的作用。
    for ratio in range(min_ratio, max_ratio + 1, step):
        ########min_sizes.append()函數即把括號內部每次得到的值依次給了min_sizes。
        min_sizes.append(min_dim * ratio / 100.)
        # print("min_size:", min_sizes)
        max_sizes.append(min_dim * (ratio + step) / 100.)
        # print("max_size:", max_sizes)

    return [min_sizes, max_sizes]
###這一步要仔細理解,即計算卷積層產生的prior_box距離原圖的比例,
# 先驗框中心點的座標會乘以scale,相當於從feature map位置映射回原圖位置,
# 比如conv4_3輸出特徵圖大小爲38*38,而輸入的圖片爲300*300,所以38*8約等於300,
# 所以映射步長爲8。這是針對300*300的訓練圖片。
scale = [8, 16, 32, 64, 100,300]
aspect_ratios = [[2], [2, 3], [2, 3], [2, 3], [2], [2]]
# mbox_source_layers = ['conv4_3', 'fc7', 'conv6_2', 'conv7_2', 'conv8_2', 'conv9_2']
def compute_default_box():
    min_sizes, max_sizes = compute_min_max_size()
    conv4_3 = np.zeros(shape=(4, 2))
    fc7 = np.zeros(shape=(6, 2))
    conv6_2 = np.zeros(shape=(6, 2))
    conv7_2 = np.zeros(shape=(6, 2))
    conv8_2 = np.zeros(shape=(4, 2))
    conv9_2 = np.zeros(shape=(4, 2))

    mbox_source_layers = [conv4_3, fc7, conv6_2, conv7_2, conv8_2, conv9_2]
    for i in range(6):
        # 每層feature中默認框的數量
        num = len(aspect_ratios[i]) * 2 + 2
        # for j in range(num):
        # 計算小正方形邊長  小邊長=min_size
        mbox_source_layers[i][0, :] = min_sizes[i]
        # 計算大正方形邊長  大邊長=sqrt(min_size*max_size)
        mbox_source_layers[i][1, :] = np.sqrt(min_sizes[i] * max_sizes[i])
        # 計算第一個長方形寬 width=sqrt(aspect_ratio)*min_size
        mbox_source_layers[i][2, 0] = np.sqrt(aspect_ratios[i][0]) * min_sizes[i]
        # 計算第一個長方形高 height=1/sqrt(aspect_ratio)*min_size
        mbox_source_layers[i][2, 1] = 1.0 / np.sqrt(aspect_ratios[i][0]) * min_sizes[i]
        # 計算第二個長方形寬 等於第一個長方形的高
        mbox_source_layers[i][3, 0] = mbox_source_layers[i][2, 1]
        # 計算第二個長方形高 等於第一個長方形的寬
        mbox_source_layers[i][3, 1] = mbox_source_layers[i][2, 0]
        # 判斷一哈是否要計算第三和第四個長方形
        if num == 6:
            # 計算第三個長方形的寬
            mbox_source_layers[i][4, 0] = np.sqrt(aspect_ratios[i][1]) * min_sizes[i]
            # 計算第三個長方形高
            mbox_source_layers[i][4, 1] = 1.0 / np.sqrt(aspect_ratios[i][1]) * min_sizes[i]
            # 計算第四個長方形寬 等於第三個長方形的高
            mbox_source_layers[i][5, 0] = mbox_source_layers[i][4, 1]
            # 計算第四個長方形高 等於第三個長方形的寬
            mbox_source_layers[i][5, 1] = mbox_source_layers[i][4, 0]

    return mbox_source_layers


if __name__ == "__main__":
    # 測試min_size, max_size
    # min_sizes, max_sizes = compute_min_max_size()
    # print("min_size: ",min_sizes)
    # print("max_size: ", max_sizes)

    # 測試默認框尺寸
    feature_map = compute_default_box()
    # conv6_2 = feature_map[2]
    for i in range(6):
        num = feature_map[i].shape[0]
        print("第%d個 feature map 小正方形邊長:"%(i+1), feature_map[i][0, 0], feature_map[i][0, 1])
        print("第%d個 feature map 大正方形邊長:"%(i+1), feature_map[i][1, 0], feature_map[i][1, 1])
        print("第%d個 feature map 第一個長方形寬:"%(i+1), feature_map[i][2, 0], " 高:", feature_map[i][2, 1])
        print("第%d個 feature map 第二個長方形寬:"%(i+1), feature_map[i][3, 0], " 高:", feature_map[i][3, 1])
        if num == 6:
            print("第%d個 feature map 第三個長方形寬:"%(i+1), feature_map[i][4, 0], " 高:", feature_map[i][4, 1])
            print("第%d個 feature map 第四個長方形寬:"%(i+1), feature_map[i][5, 0], " 高:", feature_map[i][5, 1])
        print("-*-"*20)

# [30.0, 60.0, 111.0, 162.0, 213.0, 264.0]
# [60.0, 111.0, 162.0, 213.0, 264.0, 315.0]

 6個特徵層的默認框尺寸如下:

第1個 feature map 小正方形邊長: 30.0 30.0
第1個 feature map 大正方形邊長: 42.42640687119285 42.42640687119285
第1個 feature map 第一個長方形寬: 42.42640687119285  高: 21.213203435596423
第1個 feature map 第二個長方形寬: 21.213203435596423  高: 42.42640687119285
-*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*-
第2個 feature map 小正方形邊長: 60.0 60.0
第2個 feature map 大正方形邊長: 81.60882305241266 81.60882305241266
第2個 feature map 第一個長方形寬: 84.8528137423857  高: 42.426406871192846
第2個 feature map 第二個長方形寬: 42.426406871192846  高: 84.8528137423857
第2個 feature map 第三個長方形寬: 103.92304845413263  高: 34.64101615137755
第2個 feature map 第四個長方形寬: 34.64101615137755  高: 103.92304845413263
-*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*-
第3個 feature map 小正方形邊長: 111.0 111.0
第3個 feature map 大正方形邊長: 134.09697983176207 134.09697983176207
第3個 feature map 第一個長方形寬: 156.97770542341357  高: 78.48885271170677
第3個 feature map 第二個長方形寬: 78.48885271170677  高: 156.97770542341357
第3個 feature map 第三個長方形寬: 192.25763964014536  高: 64.08587988004847
第3個 feature map 第四個長方形寬: 64.08587988004847  高: 192.25763964014536
-*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*-
第4個 feature map 小正方形邊長: 162.0 162.0
第4個 feature map 大正方形邊長: 185.75790696495264 185.75790696495264
第4個 feature map 第一個長方形寬: 229.1025971044414  高: 114.55129855222069
第4個 feature map 第二個長方形寬: 114.55129855222069  高: 229.1025971044414
第4個 feature map 第三個長方形寬: 280.59223082615813  高: 93.53074360871939
第4個 feature map 第四個長方形寬: 93.53074360871939  高: 280.59223082615813
-*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*-
第5個 feature map 小正方形邊長: 213.0 213.0
第5個 feature map 大正方形邊長: 237.13287414443406 237.13287414443406
第5個 feature map 第一個長方形寬: 301.2274887854693  高: 150.61374439273462
第5個 feature map 第二個長方形寬: 150.61374439273462  高: 301.2274887854693
-*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*-
第6個 feature map 小正方形邊長: 264.0 264.0
第6個 feature map 大正方形邊長: 288.37475617675 288.37475617675
第6個 feature map 第一個長方形寬: 373.3523804664971  高: 186.67619023324852
第6個 feature map 第二個長方形寬: 186.67619023324852  高: 373.3523804664971
-*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*-

 最後感謝xunan003博主的論文,通過他的論文讓我更加理解如何求解默認框尺寸的方法:

https://blog.csdn.net/xunan003/article/details/79186162

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章