논문 읽기/Object Detection

[Object Detection] IoU(Intersection over Union)를 이해하고 파이토치로 구현하기

AI 꿈나무 2021. 1. 2. 17:49
반응형

 안녕하세요 이번 포스팅에서는 IoU에 대해 알아보도록 하겠습니다.

 

IoU(Intersection over Union)은 무엇일까요?

 Intersection over Union은 object detector의 정확도를 측정하는데 이용되는 평가 지표입니다.

 Object detection 논문이나 대회에서 IoU 평가 지표를 쉽게 볼 수 있습니다.

 

 알고리즘이 출력한 예측 바운딩 박스는 IoU를 이용해서 평가될 수 있습니다.

 

 IoU를 적용하기 위해서는 두 가지가 필요합니다.

 

1. ground-truth bounding boxes(testing set에서 object 위치를 labeling 한것)

2. prediceted bounding boxes (model이 출력한 object 위치 예측값)

 

 이 두가지가 있으면 IoU를 적용할 수 있습니다.

 

 

 위 그림에서 object detector가 표지판을 탐지한 것을 볼 수 있습니다.

 predicted bounding box는 빨강색이고, ground-truth는 초록색 입니다.

 

 object detector가 얼마나 정확히 객체 위치를 탐지했는지 알아보기 위해 IoU를 계산해보도록 하겠습니다.

 

 

 이 공식이 IoU를 계산하는 식입니다.

 

 area of overlab은 prediceted bounding box와 ground-truth bounding box가 겹치는 부분입니다.

 area of unin은 predicted bounding box와 ground-truth bounding box를 둘러싸는 영역입니다.

 

 이 둘을 나눠서 IoU를 구할 수 있습니다.

 

왜 Intersection over Union을 사용할 까요?

 머신 러닝으로 분류 문제를 수행할 때 predicted class가 맞는지 틀렸는지 쉽게 확인할 수 있습니다.

 맞다, 틀리다 두 가지로 구분하면 되기 때문입니다. 

 

 하지만 object detection에서는 간단하지 않습니다.

 

 현실 문제에서 predicted bounding box가 정확히 ground-truth bounding box와 일치하지 경우는 거의 없습니다.

 

 model은 다양한 parameters(image pyramid scale, sliding window size, feature extraction method 등등)가 있기 때문입니다.

 

 이 때문에 predicted bounding box가 ground-truth bounding box와 얼마나 일치하는지 측정하기 위한 평가 지표를 정의한 것입니다.

 

 

 위 그림은 good, bad IoU 예시입니다.

 

 IoU가 높은 경우 predicted bounding box와 ground-truth bounding box가 거의 포개진 것을 확인할 수 있습니다.

 이처럼 IoU가 높다는 것은 model이 bounding box를 정확하게 예측했다는 의미입니다.

 

IoU(Intersection of Union) 파이토치로 구현하기

 IoU를 파이토치로 구현하기 전에 바운딩 박스의 두 가지 형식을 알아보겠습니다.

 

(1) midpoint

 midpoint 형식의 바운딩 박스는 4개의 변수를 갖습니다. (x1,y1,w,h)

 여기서 (x1,y1)은 바운딩 박스의 중앙점, (w,h)는바운딩 박스의 넓이(w), 높이(h)입니다.

 

(2) corner

 corner 형식의 바운딩 박스는 (x1,y1,x2,y2) 입니다.

 여기서 (x1,y1)은 바운딩 박스의 좌측상단좌표, (x2,y2)는 바운딩 박스의 우측하단좌표를 의미합니다.

 

[IoU Implement in Pytorch]

import torch

def intersection_over_union(boxes_preds, boxes_labels, box_format='midpoint'):

    # box 좌표는 midpoint, corners 두 가지 형식이 있습니다.

    # boxes_preds shape : (N,4) N은 bboxes의 개수 입니다.
    # boxes_labels shape : (N,4)

    if box_format == 'midpoint':
    	box1_x1 = boxes_preds[..., 0:1] - boxes_preds[..., 2:3] / 2
    	box1_y1 = boxes_preds[..., 1:2] - boxes_preds[..., 3:4] / 2
    	box1_x2 = boxes_preds[..., 0:1] + boxes_preds[..., 2:3] / 2
    	box1_y2 = boxes_preds[..., 1:2] + boxes_preds[..., 3:4] / 2
    	box2_x1 = boxes_labels[..., 0:1] - boxes_labels[..., 2:3] / 2
    	box2_y1 = boxes_labels[..., 1:2] - boxes_labels[..., 3:4] / 2
    	box2_x2 = boxes_labels[..., 0:1] + boxes_labels[..., 2:3] / 2
    	box2_y2 = boxes_labels[..., 1:2] + boxes_labels[..., 3:4] / 2

    if box_format == 'corners':
        box1_x1 = boxes_preds[..., 0:1] # (N,1)
        box1_y1 = boxes_preds[..., 1:2]
        box1_x2 = boxes_preds[..., 2:3]
        box1_y2 = boxes_preds[..., 3:4]
        box2_x1 = boxes_labels[..., 0:1]
        box2_y1 = boxes_labels[..., 1:2]
        box2_x2 = boxes_labels[..., 2:3]
        box2_y2 = boxes_labels[..., 3:4]

    x1 = torch.max(box1_x1, box2_x1)
    y1 = torch.max(box1_y1, box2_y1)
    x2 = torch.max(box1_x2, box2_x2)
    y2 = torch.max(box1_y2, box2_y2)

    # .clamp(0)은 intersect하지 않는 경우입니다.
    # 최소값을 0으로 설정합니다.
    intersection = (x2 - x1).clamp(0) * (y2 - y1).clamp(0)

    box1_area = abs((box1_x2 - box1_x1) * (box1_y2 - box1_y1))
    box2_area = abs((box2_x2 - box2_x1) * (box2_y2 - box2_y1))

    return intersection / (box1_area + box2_area - intersection + 1e-6)

 

 

 다음 포스팅에서는 비 최대 억제(non-max suppresion)를 알아보도록 하겠습니다.

 감사합니다.


출처

[1] www.youtube.com/watch?v=XXYG5ZWtjj0

[2] www.pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/

반응형