안 쓰던 블로그

Object Detection_3. 성능 평가 Metric - IOU 본문

머신러닝/머신러닝

Object Detection_3. 성능 평가 Metric - IOU

proqk 2021. 1. 17. 14:05
반응형

Box를 그렸으니 원본과 얼마나 맞아 떨어지는지를 확인해야 한다

 

IoU: Intersection over Union

모델이 예측한 결과와 실측(Ground Truth) Box가 얼마나 정확하게 겹치는가를 나타내는 지표

 

$$IoU=\frac{Area of Overlap(개별 Box가 서로 겹치는 영역)}{Area of Union(전체 Box의 합집합 영역)}$$

 

IoU의 값이 0.4정도라면 예측이 아주 맞지 않는다

값이 0.7정도라면 나쁘지 않게 맞았고, 1에 가까울 수록 예측이 맞았다고 보면 된다

목표는 당연히 IoU값이 1에 가깝게 만드는 것

얼마 이상의 값부터 맞았다고 생각할지는 보통 0.5부터 적당히 조정한다

 

IoU구하기-입력인자로 후보 박스와 실제 박스를 받아서 IOU를 계산하는 함수 생성

import numpy as np 

def compute_iou(cand_box, gt_box):

    # Calculate intersection areas
    x1 = np.maximum(cand_box[0], gt_box[0])
    y1 = np.maximum(cand_box[1], gt_box[1])
    x2 = np.minimum(cand_box[2], gt_box[2])
    y2 = np.minimum(cand_box[3], gt_box[3])
    
    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 = cand_box_area + gt_box_area - intersection
    
    iou = intersection / union
    return iou

IoU공식에서 교집합 영역과 합집합 영역을 계산해야 한다

인자값 cand_box(추측 박스)와 gt_box(실제 박스)는 x1,y1,x2,y2를 갖는다

 

교집합 영역

두 영역의 좌상단 좌표 중 큰 값, 두 영역의 우하단 좌표 중 작은 값을 구한다

위의 그림 기준으로는 안 쪽의 빨간원, 안 쪽의 파란원이 잡힐 것이다

그렇게 x1,y1,x2,y2를 구한 뒤에 x2-x1과 y2-y1을 곱해서 넓이를 구한다

코드에서 maximum 0을 한 이유는 음수가 나오지 않도록 하기 위함이다

 

합집합 영역

두 영역의 넓이를 구한 뒤, 교집합 영역을 뺀다

 

IoU값 계산

교집합/합집합

 

실습을 위한 Ground Truth 박스를 정함(임의값으로 넣음)

import cv2
import matplotlib.pyplot as plt
%matplotlib inline

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

default_dir = '/content/DLCV' #디폴트 디렉토리를 지정(절대경로 사용!!)
img = cv2.imread(os.path.join(default_dir, 'data/image/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정보를 반환 
_, regions = selectivesearch.selective_search(img_rgb, scale=100, min_size=2000)

print(type(regions), len(regions))

 

'

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)
    print('index:', index, "iou:", iou)

rect만 뽑아내어 너비와 높이를 계산하고, 위에서 만든 iou함수에 값을 전달하여 iou값을 구한다

 

 

정렬

cand_rects = [cand['rect'] for cand in regions if cand['size'] > 5000]
cand_rects.sort()
cand_rects

5000이상의 크기인 값만 정렬 후 출력해 보면 중복값이 좀 보일 수도 있다

알고리즘이 물체가 있을만한 곳을 추측해서 선택하다보니까 중복이 나올 수 있다

 

최종 코드

img = cv2.imread(os.path.join(default_dir, 'data/image/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()

처음에 그림을 가져오고, 그림을 출력한다

빨간색으로 실제 영역을 표시한다(임의값으로 인물을 잡음)

사이즈가 3000이상인 후보 박스들의 값을 보면서 iou값을 계산한다

iou값이 0.5이상이면 초록색으로 해당 후보 박스를 그린다

 

 

 

반응형
Comments