이미지를 받아 여러 변형을 가해 우리가 원하는 경계 상자로 바꿔야 합니다.
경계 상자를 설명하는 데는 2가지 방법이 있습니다. 우선 상자의 네 꼭지점을 숫자로 표시한 [xmin, ymin, xmax, ymax]와 상자의 중심 좌표와 높이와 너비를 표시한 [center_x, center_y, width, height]이 있습니다. 이번에는 후자를 사용할 것입니다.
이전에 모델을 제한하는데 "그리드"와 "앵커"를 사용했습니다. 따라서 모델이 경계 상자를 예측할 때는 이미지의 절대 좌표가 아닌, "델타"값이 됩니다.
각 탐지기는 앵커 상자를 기준으로 예측을 합니다. 이미 앵커 상자는 k-평균 클러스터로 실제 객체의 크기에 유사하게 선택되었지만, 정확하지 않습니다. 그렇기에 예측한 경계 상자가 그리드의 중심에서 얼마나 떨어져 있는지, 그리고 앵커보다 얼마나 크거나 작은지를 예측하는 이유입니다.
경계 상자의 실제 너비와 높이를 픽셀 좌표를 얻는 코드입니다.
box_w[i, j, b] = anchor_w[b] * exp(delta_w[i, j, b]) * 32
box_h[i, j, b] = anchor_h[b] * exp(delta_h[i, j, b]) * 32
지수를 취하는 이유는 상자의 너비와 높이가 음수일 수는 없기 때문입니다.
32는 입력 이미지가 416 x 416이고 그리드가 13 x 13 일 때의 값이니 이미지와 그리드에 따라 달라질 수 있는 값입니다.
경계 상자의 중심 위치를 얻는 코드입니다.
box_x[i, j, b] = (i + sigmoid(delta_x[i, j, b])) * 32
box_y[i, j, b] = (j + sigmoid(delta_y[i, j, b])) * 32
YOLO의 경우 예측된 경계 상자의 중심이 탐지기의 그리드 셀 내부에 있는 경우에만 경계 상자를 예측하도록 합니다. 따라서 인접한 그리드 셀이 동일한 객체를 동시에 예측하는 중복을 피할 수 있습니다. 이를 위해 delta_x 와 delta_y가 0과 1사이의 숫자로 제한이 되어야 하므로 sigmoid를 씌웁니다.