요약: 그레프 컷을 이용한, 객체 분리를 위한 이미지 분할 알고리즘
GrabCut 알고리즘은 이미지 분할 알고리즘 중 하나로, 이미지에서 객체를 분리하는 기술입니다. 이 알고리즘은 Microsoft Research에서 2004년에 개발되었으며, 이미지 분할에서 높은 성능을 보입니다.
방법론
GrabCut 알고리즘은 기본적으로 그래프 컷(Graph Cut) 알고리즘을 기반으로 하며, 다음과 같은 단계로 이루어집니다.
- 초기화: 입력 이미지에서 전경(foreground)과 배경(background)을 구분할 수 있는 초기 마스크(mask)생성:. 예를 들어, 사용자가 수동으로 객체를 지정하거나 또는 머신러닝 알고리즘 등을 사용하여 초기 마스크를 생성할 수 있습니다.
초기 마스크에는 전경, 배경, 그리고 불확실한 영역이 있습니다. 불확실한 영역은 전경인지 배경인지 확실하지 않은 영역입니다. - 가우시안 혼합 모델(Gaussian Mixture Model) 적용: 전경과 배경의 색상 분포를 추정하는 가우시안 혼합 모델(GMM)을 적용합니다. 전경과 배경은 각각 다른 GMM으로 모델링됩니다. 불확실한 영역에 대해서는 두 GMM을 혼합한 모델을 사용합니다.
- 에너지 함수 계산: 각 픽셀의 전경일 가능성과 배경일 가능성을 기반으로 에너지 함수를 계산합니다. 에너지 함수는 전경과 배경에 속할 가능성이 높은 픽셀에 대해서는 에너지가 작게, 그렇지 않을 경우에는 에너지가 크게 계산됩니다.
- 그래프 컷(Graph Cut) 수행: 그래프 컷 알고리즘을 사용하여 전경과 배경을 분리합니다. 그래프는 노드(node)와 엣지(edge)로 이루어져 있으며, 각 픽셀은 노드에 대응되고, 인접한 픽셀 간에는 엣지가 존재합니다. 엣지에는 가중치가 부여되는데, 이 가중치는 인접한 노드의 색상 및 에너지 함수를 기반으로 계산됩니다. 그래프 컷 알고리즘을 적용하여 전경과 배경을 구분합니다.
- 반복
전경과 배경이 충분히 분리될 때까지 단계 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
'Data science > Computer Vision' 카테고리의 다른 글
[5분 컷 리뷰] SimCLR (A Simple Framework for Contrastive Learning of Visual Representations) 리뷰 (1) | 2023.12.17 |
---|---|
[5분 컷 이해] edge detection(에지검출)과 영교차 이론 (0) | 2023.08.22 |
NMS(Non maximal supression) 계산하기, 파이썬 (0) | 2023.03.18 |
[5분 컷 이해] Morphological transformation (형태변형) 설명 (0) | 2022.09.18 |
[5분 컷 이해] Grad-CAM 의 이해 (0) | 2022.07.17 |