[CV] IOU, NMS, mAP의 이해와 실습

박경민·2023년 9월 5일
0

[Computer Vision]

목록 보기
2/25

Object Detection 성능평가 Metric- IoU

Object Detection 성능평가 Metric으로는 IoU: Intersection over Union 이 사용된다.

모델이 예측한 결과와 실측 box 가 얼마나 정확하게 겹치는가를 나타내는 지표이다.

따라서 IOU = Area of Overlap / Area of Union으로 비율로 계산한다.

IOU 실습

IOU를 계산하는 함수는 아래와 같다.

좌상단, 우하단의 겹치는 좌표를 구하고 Intersection 영역을 구한다. 각각의 박스 크기에서 Intersection 영역의 크기를 빼서 Union 영역을 구한다. 그리고나서 IOU를 반환하면 된다!

이때 주의할 점은 좌상단, 우하단에서 좌상단을 구할 땐 maximum 을, 우하단을 구할땐 minimum 함수를 사용해야 한다는 점이다. 주석으로 작성해두었다.

import numpy as np 

def compute_iou(cand_box, gt_box): # 예측, 실제 

    # Calculate intersection areas
    x1 = np.maximum(cand_box[0], gt_box[0]) # 좌상단의 경우 오른쪽, 아래가 겹치는 부분이다. (max)
    y1 = np.maximum(cand_box[1], gt_box[1]) # 좌상단의 경우 오른쪽, 아래가 겹치는 부분이다. (max)
    x2 = np.minimum(cand_box[2], gt_box[2]) # 우하단의 경우 왼쪽, 위가 겹치는 부분이다 (min)
    y2 = np.minimum(cand_box[3], gt_box[3]) # 우하단의 경우 왼쪽, 위가 겹치는 부분이다 (min)
    
    # x좌표와 y좌표 각각을 빼서 겹치는 부분 계산 (음수가 되지않도록 0이상으로 설정)
    intersection = np.maximum(x2 - x1, 0) * np.maximum(y2 - y1, 0)
    
    cand_box_area = (cand_box[2] - cand_box[0]) * (cand_box[3] - cand_box[1])
    gt_box_area = (gt_box[2] - gt_box[0]) * (gt_box[3] - gt_box[1])
    # union 영역의 크기 계산 
    union = cand_box_area + gt_box_area - intersection
    
    iou = intersection / union
    return iou

실제 ground truch 박스를 설정해보자. 설정한 gt 박스를 이미지에 그려보자!

import cv2
import matplotlib.pyplot as plt
%matplotlib inline

# 실제 box(Ground Truth)의 좌표를 아래와 같다고 가정. 
gt_box = [60, 15, 320, 420]


img = cv2.imread('./data/audrey01.jpg')
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

red = (255, 0 , 0)
img_rgb = cv2.rectangle(img_rgb, (gt_box[0], gt_box[1]), (gt_box[2], gt_box[3]), color=red, thickness=2)

plt.figure(figsize=(8, 8))
plt.imshow(img_rgb)
plt.show()

아까와 같은 코드로 region proposal 들을 담아보자.

import selectivesearch

#selectivesearch.selective_search()는 이미지의 Region Proposal정보를 반환 
img = cv2.imread('./data/audrey01.jpg')
img_rgb2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
_, regions = selectivesearch.selective_search(img_rgb2, scale=100, min_size=2000)

구한 좌표값으로 실제 리스트를 돌면서 우하단의 좌표값을 계산하고 -> IOU를 구하는 함수에다 넣자.

cand_rects = [cand['rect'] for cand in regions]
for index, cand_box in enumerate(cand_rects):
    cand_box = list(cand_box) # 튜플 -> 리스트 
    cand_box[2] += cand_box[0] # 우
    cand_box[3] += cand_box[1] # 하단값 계산 
    
    iou = compute_iou(cand_box, gt_box) #완성된 예측 좌표, 실제 좌표 IOU 계산 
    print('index:', index, "iou:", iou)

숫자가 너무 많으므로 cand['size']가 3000 이상인 것만을 대상으로 계산하고, IOU가 0.5 이상인 것만 그려보자.

img = cv2.imread('./data/audrey01.jpg')
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
print('img shape:', img.shape)

green_rgb = (125, 255, 51)
cand_rects = [cand['rect'] for cand in regions if cand['size'] > 3000]
gt_box = [60, 15, 320, 420]
img_rgb = cv2.rectangle(img_rgb, (gt_box[0], gt_box[1]), (gt_box[2], gt_box[3]), color=red, thickness=2)

for index, cand_box in enumerate(cand_rects):
    
    cand_box = list(cand_box)
    cand_box[2] += cand_box[0]
    cand_box[3] += cand_box[1]
    
    iou = compute_iou(cand_box, gt_box)
    
    if iou > 0.5:
        print('index:', index, "iou:", iou, 'rectangle:',(cand_box[0], cand_box[1], cand_box[2], cand_box[3]) )
        cv2.rectangle(img_rgb, (cand_box[0], cand_box[1]), (cand_box[2], cand_box[3]), color=green_rgb, thickness=1)
        text = "{}: {:.2f}".format(index, iou)
        cv2.putText(img_rgb, text, (cand_box[0]+ 100, cand_box[1]+10), cv2.FONT_HERSHEY_SIMPLEX, 0.4, color=green_rgb, thickness=1)
    
plt.figure(figsize=(12, 12))
plt.imshow(img_rgb)
plt.show()

index 32번이 IOU 0.63으로 가장 높은 것을 확인할 수 있다.

NMS (Non Max Suppression)

Region Proposal 을 통한 Object Detection 은 Object 가 있을만한 위치에 여러 Objection 을 만드나.. NMS 는 많은 바운딩박스 중 비슷한 위치에 있는 박스를 제거하고, 가장 적합한 박스만을 선택한다.

✅ NMS 수행 로직

  1. Detect 된 바운딩박스별로 특정 Confidence threshold 이하 바운딩박스는 제거한다. (confidence < 0.5)
  2. confidence score 순으로 내림차순 정렬하고,
  • 겹치는 다른 박스들을 보면서 IOU 를 계산한다.
  • IOU 특정 임계점 이상인 box 를 모두 제거한다. (confidence score 가 높은 박스와 겹치는 것들은 굳이 남기지 않고 하나만 남기는 것이다.)
  1. 남아있는 box 를 선택한다

따라서 confidence score 가 높을수록, IOU threshold 가 낮을수록 많은 박스가 제거된다.

Object Detection 성능평가 Metric- mAP

재현율의 변화에 따른 정밀도의 값을 평균한 성능 수치이다.

  • 성능을 나타날 땐 Inference time 과
  • AP 를 기록한다.
    YOLO 의 경우 예측 시간이 굉장히 빠르면서 성능도 좋다. 가장 정확도가 좋은 것은 RetinaNet 이며, 실시간으로 하기엔 무리가 있다.

✅ 정밀도: 예측이 참인 것 중에 실제도 참인 비율.

✅ 재현율: 실제가 참인 것 중 예측도 참인 비율.

PASCAL VOC에서는 IOU가 0.5 이상이면 성공으로 인정한다. COCO 챌린지에서는 IOC 기준을 변경해가면서 예측 성공을 적용한다.

Object Detection에서 TP, FP, FN을 보자.

FP의 경우 클래스가 잘못되었거나, IOU가 너무 떨어질 경우, 오버랩되지 않을 경우이고, FN일 경우 예측에 대해선 아예 수행하지 않은 경우이다.

여기서도 기존의 정의를 지키며

  • 정밀도 = TP / (FP + TP)
  • 재현율 = TP / (FN + TP)
    로 계산할 수 있다. 그렇다면 Confidence 임곗값에 따른 정밀도, 재현율의 변화는 어떨까?

임곗값이 높다는 것은 쉽게 예측을 하지 않다가 확실할 때에만 예측하겠다는 것이다. 그렇게되면 FP은 줄어들기 때문에 정밀도는 높아지고, Negative 로 예측한 것이 많아지는데 가짜일 확률이 높아지므로 FN이 높아져서 재현율이 낮아진다. 임곗값이 낮아져서 예측을 난사하게 되면, FP가 높아져서 정밀도가 낮아지고 재현율은 올라간다.

이렇게 trade-off 한 관계가 있으므로 결국 '평균적으로 좋은'것이 중요하고, 이를 AP라 한다. (Average Precision)


따라서 이 면적이 클수록 좋다.

confidence 가 0.9라는 것은 확실한 것만 detection 하겠다는 것이고, 정밀도는 높고 재현율은 낮다.
confidence 가 낮아질수록 예측을 더 많이하게 된다. 많이할수록 FP 가 높아지므로 정밀도가 낮아지고 재현율이 높아진다.

변화에 따라 그래프를 그려보면 아래와 같고, 결국 너비가 AP이다.

✅ COCO Challenge 에서의 mAP

  • 예측 성공을 위한 IOU 를 0.5 이상으로 고정한 PASCAL VOC 와 달리, COCO에서는 다양한 범위로 IOU 를 설정한다.
  • AP@[.50:.05:.95] 는 시작 IOU 기준 0.5, 증가 0.05, 최종 0.95 에 따른 AP값을 의미한다.
  • 추가적으로 크기의 유형에 따른 mAP도 측정한다.

업로드중..

IOU 값을 증가시킨다는 것은 결국 성공으로 인정한다는 기준이 높아진다는 것이며, 같은 모델이라 하더라도 AP가 줄어드는 결과를 낳게 될 것이다.

profile
Mathematics, Algorithm, and IDEA for AI research🦖

0개의 댓글