컴퓨터 비전/Object Detection

[Object Detection] Selective Search (선택적 탐색)

고집호랑이 2023. 4. 1. 07:22

개요 

이전 포스팅에서 배운 Sliding Window 방식은 일정 크기의 window가 이미지의 모든 영역을 sliding하면서 객체를 찾기 때문에 계산량이 매우 많다는 단점이 있었습니다.

 

이 단점을 보완하기 위해서 객체가 있을만한 후보 영역을 미리 찾고 그 영역 내에서만 객체를 찾는 방식Region Proposal(영역 추정) 방식이라고 합니다.

 

오늘은 이 Region Proposal의 대표적인 방법 중 하나이자 초기 Object Detection 모델인 R-CNN에 사용된 Selective Search에 대해서 살펴보도록 하겠습니다.

 

Selective Search 과정

Selective Search 이전에 물체가 있을만한 영역을 모두 조사해보는 Exhaustive Search 방법이 있었습니다. 

 

Selective Search는 이에 Segmetation을 결합해 Exhaustive Search를 개선시킨 방법입니다.

 

Selective Search의 과정은 다음과 같습니다. 

 

 

1. 초기에는 원본 이미지로부터 각각의 object들이 1개의 개별 영역에 담길 수 있도록 수많은 영역들을 생성합니다. (이때 object들을 놓치지 않기 위해서 Over Segmenatation을 해준다.)

 

2.  이후 아래 그림의 알고리즘에 따라서 유사도가 높은 것들을 하나의 Segmetation(영역)으로 합쳐주는데 그 자세한 과정은 다음과 같습니다.

 

$R = {r_1, ... , r_n}$ - 최초 Segmentation을 통해서 나온 초기 n개의 후보 영역들

$S$ - 영역들 사이의 유사도 집합

 

- 색상, 무늬, 크기, 형태를 고려하여 각 영역들 사이의 유사도를 계산

- 유사도가 가장 높은 $r_i$와 $r_j$ 영역을 합쳐 새로운 $r_t$ 영역을 생성

- $r_i$와 $r_j$ 영역과 관련된 유사도는 S 집합에서 삭제

- 새로운 $r_t$ 영역과 나머지 영역의 유사도를 계산하여 $r_t$의 유사도 집합 $S_t$ 생성

- 새로운 영역의 유사도 집합 $S_t$와 영역 $r_t$를 기존의 $S, R$ 집합에 추가

 

3. 2번 과정을 여러 번 반복하여 최종 후보 영역을 도출합니다.

아래 그림과 같이 엄청나게 많았던 초기 영역들이 2번 과정의 반복 횟수가 많아질수록 유사도가 높은 영역들이 합쳐져 후보 영역들이 줄어드는 것을 확인할 수 있습니다.

 

 

이제 최종 후보 영역들에 대해서 CNN을 통한 Classifiaction과 Bounding box regression을 해주면 Object Detection이 수행되는 것이죠. 그리고 실제로 이것이 최초의 딥러닝 기반 Object Detection 알고리즘인 R-CNN의 전반적인 과정입니다. 

 

Selective Search 실습

Selective Search의 실습과 앞으로의 모든 딥러닝 기반 Object Detection 알고리즘 실습은 편의상 무료로 GPU를 사용할 수 있는 Colab 환경에서 진행하도록 하겠습니다.

 

selective search 설치 

!pip install selectivesearch

 

폴더 생성 및 이미지 로드 

!mkdir /content/data
!wget -O /content/data/animals.jpg https://raw.githubusercontent.com/goodhsm2000/DLCV_ex/main/animals.jpeg

 

다운받은 이미지를 matplotlib을 이용해 시각화 

import selectivesearch
import cv2
import matplotlib.pyplot as plt
import os
%matplotlib inline

# 이미지를 cv2로 로드하고 matplotlib으로 시각화 
img = cv2.imread('./data/animals.jpg')
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
print('img shape:', img.shape)

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

코드 실행 결과

 

Selective Search를 활용해 이미지의 후보 영역 살펴보기

import selectivesearch 

# selectivesearch.selective_search()는 이미지의 Region Proposal정보를 반환 
# 첫 번째 반환 값은 필요없으므로 _로 표현
_, regions = selectivesearch.selective_search(img_rgb, scale=100, min_size=2000)

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

 

출력 결과

 

위 그림은 출력값의 일부를 가져온 것입니다. regions은 list 형태로 Selective Search 방법에 의해 나온 최종 후보 영역들의 정보를 담고 있습니다. 

 

예시 그림에서는 29개의 후보 영역들이 나왔고 출력된 후보 영역들의 'rect', 'size', 'labels' 정보는 다음을 의미합니다.

  • 'rect' : 후보 영역의 min x, y값과 width와 height 값, 즉 bounding box 정보 값
  • 'size' : 후보 영역의 크기
  • 'labels' : 'rect'으로서 나온 후보 영역의 bounding box 안에 있는 Object들의 고유 ID

 

후보 영역들의 Bounding Box 시각화하기

즉 저희는 regions에 있는 'rect' 정보를 이용해야합니다.

# rect 정보만 뽑아오기
cand_rects = [cand['rect'] for cand in regions]

# opencv의 rectangle()을 이용하여 시각화
# rectangle()은 이미지와 좌상단 좌표, 우하단 좌표, box 컬러색, 두께등을 인자로 입력하면 원본 이미지에 box를 그려줌. 

# box 컬러색 지정
green_rgb = (125, 255, 51)
img_rgb_copy = img_rgb.copy()
for rect in cand_rects:
    
    left = rect[0]
    top = rect[1]
    # rect[2], rect[3]은 너비와 높이이므로 우하단 좌표를 구하기 위해 좌상단 좌표에 각각을 더함. 
    right = left + rect[2]
    bottom = top + rect[3]
    
    img_rgb_copy = cv2.rectangle(img_rgb_copy, (left, top), (right, bottom), color=green_rgb, thickness=2)
    
plt.figure(figsize=(8, 8))
plt.imshow(img_rgb_copy)
plt.show()

후보 영역 bounding box 시각화

저는 얼룩말을 detect하고 싶은데 출력 결과를 보면 현재 원치 않은 후보 영역들이 너무 많은 것을 확인할 수 있습니다.

 

따라서 이 후보 영역들 중 size가 너무 작거나 큰 후보 영역들은 제외하도록 하겠습니다.

 

후보 영역들 재설정

cand_rects = [cand['rect'] for cand in regions if 10000 < cand['size'] < 80000]

green_rgb = (125, 255, 51)
img_rgb_copy = img_rgb.copy()
for rect in cand_rects:
    
    left = rect[0]
    top = rect[1]
    # rect[2], rect[3]은 너비와 높이이므로 우하단 좌표를 구하기 위해 좌상단 좌표에 각각을 더함. 
    right = left + rect[2]
    bottom = top + rect[3]
    
    img_rgb_copy = cv2.rectangle(img_rgb_copy, (left, top), (right, bottom), color=green_rgb, thickness=2)
    
plt.figure(figsize=(8, 8))
plt.imshow(img_rgb_copy)
plt.show()

후보 영역 조정

 

Selective Search 코드에 대해서 더 자세히 알고싶은 분은 아래 링크를 참고하시면 되겠습니다.

 

https://github.com/AlpacaTechJP/selectivesearch

 

GitHub - AlpacaTechJP/selectivesearch: Selective Search Implementation for Python

Selective Search Implementation for Python. Contribute to AlpacaTechJP/selectivesearch development by creating an account on GitHub.

github.com

 

다음 포스팅에서는 딥러닝 기반 Object Detection 알고리즘들을 본격적으로 살펴보기 전에 알아야할 IOU, NVM 개념과 성능 평가 지표인 mAP에 대해서 설명하도록 하겠습니다.

 

Reference

●  https://www.inflearn.com/course/딥러닝-컴퓨터비전-완벽가이드/dashboard - 인프런 강의

 

●  https://mainpower4309.tistory.com/27