사냥꾼의 IT 노트

[딥러닝]IOU에 대해서 이해해보자 본문

딥러닝

[딥러닝]IOU에 대해서 이해해보자

가면 쓴 사냥꾼 2022. 7. 7. 13:07
IOU? Intersection Over Union?

Intersection Over Union은 object detection에서 성능 평가를 위해 사용되는 도구다. 정답 영역 및 예측 영역은 대부분 직사각형으로 설정한다. 정의는 아래 사진과 같다.

정답 영역: Groung-truth bounding box / 예측 영역: Predicted bounding box

위 사진과 같이 정답 영역과 예측 영역이 직사각형의 형태로 존재하는데, 이 두 영역이 겹치는 부분이 많을수록 정확도가 올라가고 IOU의 값은 크다고 본다. 즉, IOU의 값이 클수록 "오브젝트 검출이 잘 되고 있다"라고 보는 것이다.


IOU의 값

IOU의 최대값은 정답 영역과 예측 영역이 완전히 겹치는 정도이며, 값은 1이다. 반대로 정답 영역과 예측 영역이 완전히 겹치지 않는 정도가 최소값이며, 이 값은 0이다.


IOU의 계산 방법

IOU를 계산하기 위해선 기본적으로 다음과 같은 네개의 값이 필요하다.

  • x: 영역 중심의 x 좌표
  • y: 영역 중심의 y 좌표
  • w: 영역의 폭(너비)
  • h: 영역의 높이

이 때, A를 정답 영역, B를 예측 영역이라 가정하면

교집합 영역/합집합 영역

으로 IOU를 계산할 수 있다.


필자가 YOLO 모델을 개발할 때 쓸 가장 중요한 도구라고 봐도 무방하다. YOLO의 최종 목표는 결국 이미지나 영상에서 오브젝트를 검출하는 것인데 이를 계산하는 도구가 바로 IOU이기 때문이다. 

def iou(yolo_pred_boxes, ground_truth_boxes):
  # Reference : https://github.com/nilboy/tensorflow-yolo/blob/python2.7/yolo/net/yolo_tiny_net.py#L105
  """calculate ious
  Args:
    yolo_pred_boxes: 4-D tensor [CELL_SIZE, CELL_SIZE, BOXES_PER_CELL, 4]  ====> (x_center, y_center, w, h)
    ground_truth_boxes: 1-D tensor [4] ===> (x_center, y_center, w, h)
  Return:
    iou: 3-D tensor [CELL_SIZE, CELL_SIZE, BOXES_PER_CELL]
  """
  boxes1 = yolo_pred_boxes
  boxes2 = ground_truth_boxes

  boxes1 = tf.stack([boxes1[:, :, :, 0] - boxes1[:, :, :, 2] / 2, boxes1[:, :, :, 1] - boxes1[:, :, :, 3] / 2,
                     boxes1[:, :, :, 0] + boxes1[:, :, :, 2] / 2, boxes1[:, :, :, 1] + boxes1[:, :, :, 3] / 2])
  boxes1 = tf.transpose(boxes1, [1, 2, 3, 0])
  boxes2 = tf.stack([boxes2[0] - boxes2[2] / 2, boxes2[1] - boxes2[3] / 2,
                     boxes2[0] + boxes2[2] / 2, boxes2[1] + boxes2[3] / 2])
  boxes2 = tf.cast(boxes2, tf.float32)

  # calculate the left up point
  lu = tf.maximum(boxes1[:, :, :, 0:2], boxes2[0:2])
  rd = tf.minimum(boxes1[:, :, :, 2:], boxes2[2:])

  # intersection
  intersection = rd - lu

  inter_square = intersection[:, :, :, 0] * intersection[:, :, :, 1]

  mask = tf.cast(intersection[:, :, :, 0] > 0, tf.float32) * tf.cast(intersection[:, :, :, 1] > 0, tf.float32)

  inter_square = mask * inter_square

  # calculate the boxs1 square and boxs2 square
  square1 = (boxes1[:, :, :, 2] - boxes1[:, :, :, 0]) * (boxes1[:, :, :, 3] - boxes1[:, :, :, 1])
  square2 = (boxes2[2] - boxes2[0]) * (boxes2[3] - boxes2[1])

  return inter_square / (square1 + square2 - inter_square + 1e-6)

YOLO v1 모델을 구현할 때 쓴 IOU 함수이다. 코드를 보면 알겠지만 boxes1을 예측 영역, boxes2를 정답 영역으로 정의를 하고 계산을 진행한다.