[CV] IoU loss 와 GIoU 설명

Hyungeun Lee·2024년 8월 25일

CV

목록 보기
2/4

지난 포스트에서는 컴퓨터 비전의 객체 검지 태스크에서 중요하게 사용되는 스코어인 Intersection over Union (IoU)의 정의와 Python 구현을 다뤘습니다. 이번 포스트에서는 지난 글의 마지막에 남아있던 의문점인 "그래서 이 값을 어떻게 모델 학습에 사용하는지?"와 IoU를 좀 더 일반화한 Generalized Intersection over Union (GIoU)에 대해서 다뤄보고자 합니다.

IoU loss

지난 시간에 다뤘던 IoU 값은 bbox A와 B가 있다고 가정했을 때, 다음과 같이 정의할 수 있었습니다.

IoU=ABABIoU = \frac{|A \cap B|}{|A \cup B|}

이 식을 통해 얻을 수 있는 인사이트는 다음과 같습니다.

  • 두 박스가 완전히 겹치면 IoU 값은 1이 되고, 두 박스가 겹치지 않으면 0이 된다.
  • 합집합과 교집합의 비율로 값을 계산하기 때문에 bbox의 크기 비율의 영향을 받지 않는다. (e.g., 동일한 gt, pred bbox를 두 배 키워도 IoU값은 동일함.)
  • 아래 그림에서 알 수 있듯, bbox의 꼭짓점 좌표간의 오차인 L2L_2 loss로 잡지 못하는 prediction의 퀄리티 차이를 IoU를 사용하면 어느정도 알 수 있다.

이제 이 IoU 값을 loss로 활용하려면 어떻게 해야할까요? 위 인사이트를 통해 알 수 있는 것은 bbox 예측이 잘되면 잘될수록 IoU값은 커진다는 것입니다. 일반적으로 loss 값은 작아지면 작아질수록 예측 성능이 높아진다는 것을 의미하므로 우리는 1에서 IoU값을 빼는 전략을 사용할 것입니다. 다음과 같이 말이죠!

LIoU=1IoU\mathcal{L}_{IoU} = 1 - IoU

생각보다 간단하죠..? 사실 이게 IoU loss의 끝입니다..
만약 bbox가 완전히 겹치는 방향으로 무한히 간다면 loss 값은 0에 수렴해갈 것이고, bbox예측이 gt에서 멀어지면 멀어질수록 loss 값은 1을 향해 나아갈 것입니다.
그런데,,이 loss에는 문제가 하나 존재합니다. prediction bbox와 ground truth bbox가 겹치지 않는 상황을 가정해볼게요. 이 때 prediction bbox가 gt bbox와 엄청 멀리 떨어져 있건 약간 가깝게 있건 상관없이 IoU 값은 0이고 loss는 1이 될거에요..이렇게 되면 (물론 L1,L2L_1, L_2 loss의 결합으로 극복 가능하지만) 모델 입장에서는 prediction이 gt로부터 얼마나 많이 엉뚱한 예측(?)을 했는지 알 수 없을 거에요. 그러면 자연스럽게 학습이 저해되는 이슈가 발생하겠죠. 이를 극복하기 위해 나온 metric이 바로 GIoU입니다. 다음 챕터에서 이 값에 대해서 알아보도록 할게요.

GIoU

IoU의 한계점을 극복하기 위해 제안된 GIoU는 두 박스가 겹치지 않을 때도 의미 있는 값을 제공합니다. GIoU의 기본 아이디어는 두 박스를 모두 포함하는 가장 작은 박스 C(이하 'enclosing box')를 고려하는 것입니다. GIoU는 다음과 같이 정의할 수 있습니다:

GIoU=IoUC(AB)CGIoU = IoU - \frac{|C - (A \cup B)|}{|C|}

GIoU의 특징을 살펴보면 다음과 같이 정리할 수 있어요.

  • 두 박스가 완전히 겹치면 GIoU는 IoU와 마찬가지로 1이 됩니다.
  • 두 박스가 겹치지 않을 때, GIoU는 음수 값을 가질 수 있습니다. 이는 두 박스 사이의 떨어진 거리를 반영한다는 것을 의미합니다.
  • 이에 따라 GIoU 값의 범위는 -1에서 1 사이가 됩니다.

GIoU의 장점은 위에서도 알 수 있듯, IoU와 다르게 두 박스가 겹치지 않을 때도 의미 있는 gradient를 제공할 수 있습니다. GIoU를 loss 함수로 사용할 때는 IoU Loss와 유사하게 다음과 같이 정의합니다

LGIoU=1GIoU\mathcal{L}_{GIoU} = 1 - GIoU

이 손실 함수는 GIoU가 1일 때(즉, 예측이 완벽할 때) 0이 되고, GIoU가 -1일 때(즉, 두 박스가 매우 멀리 떨어져 있을 때) 2가 됩니다.

GIoU의 Python 구현

GIoU를 Python으로 구현해보겠습니다. 이전 포스트에서 사용한 IoU 함수를 기반으로 확장하겠습니다:

class Bbox:
    def __init__(self, x1, y1, x2, y2):
        assert x2 > x1 and y2 > y1
        self.top_left = (x1, y1)
        self.bottom_right = (x2, y2)
    
    def area(self):
        width = self.bottom_right[0] - self.top_left[0]
        height = self.bottom_right[1] - self.top_left[1]
        return width * height
    
    def intersection(self, other):
        x1 = max(self.top_left[0], other.top_left[0])
        y1 = max(self.top_left[1], other.top_left[1])
        x2 = min(self.bottom_right[0], other.bottom_right[0])
        y2 = min(self.bottom_right[1], other.bottom_right[1])
        
        if x2 <= x1 or y2 <= y1:
            return 0
        
        return (x2 - x1) * (y2 - y1)
    
    def iou(self, other):
        intersection_area = self.intersection(other)
        union_area = self.area() + other.area() - intersection_area
        
        if union_area == 0:
            return 0
        
        return intersection_area / union_area
    
    def enclosing_box(self, other):
        x1 = min(self.top_left[0], other.top_left[0])
        y1 = min(self.top_left[1], other.top_left[1])
        x2 = max(self.bottom_right[0], other.bottom_right[0])
        y2 = max(self.bottom_right[1], other.bottom_right[1])
        return Bbox(x1, y1, x2, y2)
    
    def giou(self, other):
        iou = self.iou(other)
        enclosing = self.enclosing_box(other)
        
        c_area = enclosing.area()
        union_area = self.area() + other.area() - self.intersection(other)
        
        giou = iou - (c_area - union_area) / c_area
        return giou

# test
box1 = Bbox(0, 0, 5, 5)
box2 = Bbox(3, 3, 8, 8)
print(f"IoU: {box1.iou(box2):.4f}")
print(f"GIoU: {box1.giou(box2):.4f}")

이 구현에서 추가된 주요 내용은 다음과 같습니다:

  • enclosing_box: 두 박스를 모두 포함하는 가장 작은 박스를 계산합니다.
  • giou: GIoU를 계산합니다. 이 메서드는 IoU, enclosing box, 그리고 두 박스의 합집합 면적을 이용하여 GIoU를 계산합니다.

이번 포스트에서는 object detection 분야에서 중요한 역할을 하는 IoU(Intersection over Union)의 개념을 확장한 GIoU(Generalized Intersection over Union)에 대해 알아보았습니다. 다음 포스트에서는 위 GIoU를 다룬 논문인 Generalized Intersection over Union: A Metric and A Loss for Bounding Box Regression에 대한 상세한 리뷰를 다뤄보도록 하겠습니다!

읽어주셔서 감사드리고 언제나 피드백 및 댓글은 환영입니다~~ㅎㅎ

0개의 댓글