IoU(Intersection over Union)의 목적과 개념
어느 인공지능 모델이든 성능을 평가하기 위한 지표가 필요하다. Object Detection 모델은 일반적인 분류 모델과는 다른 bounding box라는 아웃풋을 출력한다. 따라서 Object Detection 모델의 성능을 측정(목적)하기 위해 새로운 성능 측정 지표가 필요하고, 이것이 바로 IoU(Intersection over Union)이다. IoU는 모델이 예측한 결과(Predicted Bounding box)와 실제(Ground Truth Bounding box)가 얼마자 정확하게 겹치는가(개념)를 나타낸다.
IoU의 계산은 다음과 같이 한다.
IoU에 따른 Detection 성능
기준을 어떻게 설정하는지에 따라 달라질 수 있지만 보통은 다음과 같이 판단한다.
0.3 <= IoU < 0.7 Poor
0.7 <= IoU < 0.9 Good
0.9 <= IoU Excellent
IoU 구현 실습
입력인자로 후보 박스와 실제 박스를 받아서 IOU를 계산하는 함수 생성
import numpy as np
def compute_iou(cand_box, gt_box): #cand_box 와 gt_box 형태 : [좌상단 x좌표, y좌표, 우하단 x좌표, y좌표]
# 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) #<2>
cand_box_area = (cand_box[2] - cand_box[0]) * (cand_box[3] - cand_box[1]) # <2> + <3>
gt_box_area = (gt_box[2] - gt_box[0]) * (gt_box[3] - gt_box[1]) # <1> + <2>
union = cand_box_area + gt_box_area - intersection # ( <2> + <3> ) + ( <1> + <2> ) - <2> = <1> + <2> + <3>
iou = intersection / union # <2> / <1> + <2> + <3>
return iou
selective_search를 이용하여 바운딩 박스 좌표를 구한 후 iou계산하기
import selectivesearch
#selectivesearch.selective_search()는 이미지의 Region Proposal정보를 반환
img = cv2.imread('./data/audrey01.jpg') #지정된 경로의 이미지 파일이 읽혀져서 OpenCV에서 사용할 수 있는 형식인 Numpy 배열로 반환
img_rgb2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # #cv2.imread()로 이미지 가져오면 BGR 형태이고, matplotlib으로 이미지 표시하려면 RGB형태여야 해서 바꿔주는 것
_, regions = selectivesearch.selective_search(img_rgb2, scale=100, min_size=2000) #regions : object가 있을 만한 위치
cand_rects = [cand['rect'] for cand in regions] #cand['rect'] : [(박스1의 x1,y1,W,H),(박스2의 x1,y1,W,H),,,,,]
for index, cand_box in enumerate(cand_rects):
cand_box = list(cand_box)
cand_box[2] += cand_box[0] #cand_box[0] : 박스의 좌상단 x좌표, cand_box[2] : 박스의 너비, 따라서 cand_box[2] : 박스의 우하단 x좌표
cand_box[3] += cand_box[1] #cand_box[1] : 박스의 좌상단 y좌표, cand_box[2] : 박스의 높이, 따라서 cand_box[3] : 박스의 우하단 y좌표
iou = compute_iou(cand_box, gt_box)
print('index:', index, "iou:", iou)
sel바운딩 박스를 size와 iou로 선별 후 시각화
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] #크기가 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: #gt_box와의 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()
Reference
'컴퓨터비전' 카테고리의 다른 글
Object Detection 성능 평가 지표 mAP with 정밀도와 재현율 (0) | 2024.02.17 |
---|---|
NMS(Non Max Supression)의 이해 (0) | 2024.02.17 |
Region Proposal(영역 추정) - Selective Search 기법 (0) | 2024.02.14 |
Object Localization with Classification (0) | 2024.02.12 |
object detection 주요 구성 요소 및 어려운 이유 (1) | 2024.02.11 |