본문 바로가기
딥러닝관련/Detection

SSD(single shot detector) 코드 분석 0. (prior box)

by 머리올리자 2022. 5. 17.

SSD에서는 ground truth box, predict box 이외에도 prior box를 미리 정의하여 학습에 사용

 

1. Feature map size

       - [38, 19, 10, 5, 3, 1]

2. shrink range(stride)

       - [8, 16, 32, 64, 100, 300]

3. box size(min, max)

       - [30, 60, 111, 162, 213, 264] / [60, 111, 162, 213, 264, 315]

4. aspect_ratio

       - [[2], [2, 3], [2, 3], [2, 3], [2], [2]]

 

실제 구현상은 어떻게 되어 있나 보자

# https://github.com/qfgaohao/pytorch-ssd        
    
    """Generate SSD Prior Boxes.

    It returns the center, height and width of the priors. The values are relative to the image size
    Args:
        specs: SSDSpecs about the shapes of sizes of prior boxes. i.e.
            specs = [
                SSDSpec(38, 8, SSDBoxSizes(30, 60), [2]),
                SSDSpec(19, 16, SSDBoxSizes(60, 111), [2, 3]),
                SSDSpec(10, 32, SSDBoxSizes(111, 162), [2, 3]),
                SSDSpec(5, 64, SSDBoxSizes(162, 213), [2, 3]),
                SSDSpec(3, 100, SSDBoxSizes(213, 264), [2]),
                SSDSpec(1, 300, SSDBoxSizes(264, 315), [2])
            ]
        image_size: image size.
        clamp: if true, clamp the values to make fall between [0.0, 1.0]
    Returns:
        priors (num_priors, 4): The prior boxes represented as [[center_x, center_y, w, h]]. All the values
            are relative to the image size.
    """


    for spec in specs:
        scale = image_size / spec.shrinkage
        for j, i in itertools.product(range(spec.feature_map_size), repeat=2):
            x_center = (i + 0.5) / scale # normalize
            y_center = (j + 0.5) / scale # normalize

            # SQUARE BOX : SMALL SIZE
            size = spec.box_sizes.min
            h = w = size / image_size # ORIGINAL BOX SIZE / IMAGE SCALE
            # feature map point, feature map point, relative box scale, relative box scale
            priors.append([x_center, y_center, w, h])

            # SQUARE BOX : BIG SIZE
            size = math.sqrt(spec.box_sizes.max * spec.box_sizes.min) # SQUARE_ROOT(BIG * SMALL)
            h = w = size / image_size
            priors.append([x_center, y_center, w, h])

            # CHANGE RATIO OF THE SMALL SIZED BOX
            size = spec.box_sizes.min
            h = w = size / image_size
            for ratio in spec.aspect_ratios:
                ratio = math.sqrt(ratio)
                priors.append([x_center, y_center, w * ratio, h / ratio]) # increase width, decrease height 
                priors.append([x_center, y_center, w / ratio, h * ratio]) # decrease width, increase height

 

38 x 38을 예시로 들면

 

scale = 300 / 8 = 37.5

 

j, i 가 0, 0 일 때

x_center = (0 + 0.5) / 37.5 (scale)

y_center = (0 + 0.5) / 37.5 (scale)


 - 0.5를 더해주는 이유는 center 지점을 찾으려하는 이유로 생각되며

 - 37.5로 나누는 이유는 normalize를 위함이라고 생각됨


square box(min)

미리정의한 minimum box 사이즈(30)를 가져와 image_size를 나눠 비율을 계산하고

 

h = w = 30 / 300 = 0.1

 

prior 리스트에 append 한다

 

([x_center, y_center, w, h])  -> ([0.013333333333333334, 0.013333333333333334, 0.1, 0.1])

 

 

square box(max)

미리정의한 maximum box 사이즈(60)를 가져오며 값을 새로 다시 정의한다.

size = math.sqrt(spec.box_sizes.max * spec.box_sizes.min)

size = root(60 * 30) = 42.426406871

 

h = w = 42.426406871 / 300 = 0.14142135

이를 또 append 한다

([x_center, y_center, w, h])  -> ([0.013333333333333334, 0.013333333333333334, 0.14142135, 0.14142135])

 

 

Rectangle Box(modified from the small box)

 

minimum box 사이즈(30)를 가져와 ratio에 따라 변형한다.

h = w = 30 / 300 = 0.1

 

38일 때의 aspect ratio는 [2]

 

1. aspect ratio에 root 장착 -> root(2) -> 1.4142

2-1) width 늘리고, height 줄이고 -> (x_center, y_center, w * ratio, h / ratio)

2-2) width 줄이고, height 늘리고 -> (x_center, y_center, w / ratio, h * ratio)

 

결국 feature map size 38 x 38에서는 4개의 box(square 2개, rectangle 2개) 가 생기며총 38 x 38 x 4 = 5776개의 box가 생겨나는 것이다.

 


center 좌표를 계산할 때는 실제 연산시 줄어들 사이즈만큼 normalize해서 계산하는 반면 (x_center = (i + 0.5) / 37.5 (scale))

box의 height width 구할 때는 pre-defined한 box size에서 pre-defined image size를 나눈다. (h=w=size / image_size)


한 눈에 들어올 수 있게 아래와 같이 정리해봄

여기서

center 좌표는 feature map 사이즈를 기반으로,

width, height는 input image 사이지를 기반으로

되어 있으며

 

모두 해당 사이즈로 나누어 0~1로 normalize되어 있다는 것이다.