Data science/Computer Vision

[이미지 분할] Grabcut 사용법

연금(Pension)술사 2023. 4. 26. 23:06

요약: 그레프 컷을 이용한, 객체 분리를 위한 이미지 분할 알고리즘


GrabCut 알고리즘은 이미지 분할 알고리즘 중 하나로, 이미지에서 객체를 분리하는 기술입니다. 이 알고리즘은 Microsoft Research에서 2004년에 개발되었으며, 이미지 분할에서 높은 성능을 보입니다.

 

방법론


GrabCut 알고리즘은 기본적으로 그래프 컷(Graph Cut) 알고리즘을 기반으로 하며, 다음과 같은 단계로 이루어집니다.

  1. 초기화: 입력 이미지에서 전경(foreground)과 배경(background)을 구분할 수 있는 초기 마스크(mask)생성:. 예를 들어, 사용자가 수동으로 객체를 지정하거나 또는 머신러닝 알고리즘 등을 사용하여 초기 마스크를 생성할 수 있습니다.
    초기 마스크에는 전경, 배경, 그리고 불확실한 영역이 있습니다. 불확실한 영역은 전경인지 배경인지 확실하지 않은 영역입니다.
  2. 가우시안 혼합 모델(Gaussian Mixture Model) 적용: 전경과 배경의 색상 분포를 추정하는 가우시안 혼합 모델(GMM)을 적용합니다. 전경과 배경은 각각 다른 GMM으로 모델링됩니다. 불확실한 영역에 대해서는 두 GMM을 혼합한 모델을 사용합니다.
  3. 에너지 함수 계산: 각 픽셀의 전경일 가능성과 배경일 가능성을 기반으로 에너지 함수를 계산합니다. 에너지 함수는 전경과 배경에 속할 가능성이 높은 픽셀에 대해서는 에너지가 작게, 그렇지 않을 경우에는 에너지가 크게 계산됩니다.
  4. 그래프 컷(Graph Cut) 수행: 그래프 컷 알고리즘을 사용하여 전경과 배경을 분리합니다. 그래프는 노드(node)와 엣지(edge)로 이루어져 있으며, 각 픽셀은 노드에 대응되고, 인접한 픽셀 간에는 엣지가 존재합니다. 엣지에는 가중치가 부여되는데, 이 가중치는 인접한 노드의 색상 및 에너지 함수를 기반으로 계산됩니다. 그래프 컷 알고리즘을 적용하여 전경과 배경을 구분합니다.
  5. 반복
    전경과 배경이 충분히 분리될 때까지 단계 2에서 4를 반복

 

코드: Python3


1. Grabcut할 이미지를 불러옵니다.

import cv2
import numpy as np

# 입력 이미지 로드
img = cv2.imread('input_image.jpg')

2. 초기화: 초기 마스크, 전경 후경의 모델(Gaussian mixture model)에 사용되는 특징값 저장.

# 초기 마스크 생성 (전경, 배경, 불확실한 영역)
mask = np.zeros(img.shape[:2], np.uint8)
bgdModel = np.zeros((1,65), np.float64)
fgdModel = np.zeros((1,65), np.float64)

3. ROI 계산

# 전경과 배경 좌표 지정
rectangle = (365, 362, 44, 37)
# 또는 전경과 배경 지정 (마우스로)
rectangle = cv2.selectROI(img)

4. Grabcut 적용

# GrabCut 알고리즘 적용
cv2.grabCut(img, mask, rectangle, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)

5. 결과 출력: "np.where((mask==2)|(mask==0), 0, 1)"는 NumPy의 where() 함수를 사용하여 마스크에서 전경에 해당하는 부분을 추출하는 코드입니다. mask는 GrabCut 알고리즘을 적용한 결과 생성된 마스크이며, 마스크의 값은 0, 1, 2, 3 네 가지 값으로 구성됩니다. 이 중에서 값이 0과 2는 배경을 나타내고, 값이 1과 3은 전경을 나타냅니다. 따라서, mask==2 또는 mask==0인 부분은 배경에 해당하므로 0으로, 그 외의 부분은 전경에 해당하므로 1로 변환하여 반환합니다. 이를 통해 전경 부분을 추출할 수 있습니다.

# 결과 출력
mask2 = np.where((mask==2)|(mask==0), 0, 1).astype('uint8')
result = img * mask2[:, :, np.newaxis]

cv2.imshow('Input Image', img)
cv2.imshow('GrabCut Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

전체코드


// 마우스로 좌표측정방식
import cv2
import numpy as np

# 입력 이미지 로드
img = cv2.imread('input_image.jpg')

# 초기 마스크 생성 (전경, 배경, 불확실한 영역)
mask = np.zeros(img.shape[:2], np.uint8)
bgdModel = np.zeros((1,65), np.float64)
fgdModel = np.zeros((1,65), np.float64)

# 전경과 배경 지정 (마우스로)
rect = cv2.selectROI(img)

# GrabCut 알고리즘 적용
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)

# 결과 출력
mask2 = np.where((mask==2)|(mask==0), 0, 1).astype('uint8')
result = img * mask2[:, :, np.newaxis]

cv2.imshow('Input Image', img)
cv2.imshow('GrabCut Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

References


1. “GrabCut” — Interactive Foreground Extraction using Iterated Graph Cuts https://cvg.ethz.ch/teaching/cvl/2012/grabcut-siggraph04.pdf

반응형