OpenCV - 레이블링

2 분 소요

레이블링

앞서 공부한 이진화 및 모폴로지를 수행하고 나면 주요 객체와 배경 영역을 구분할 수 있게 된다. 그 다음에는 객체 단위 분석을 통해 각 객체를 분할하여 특징을 분석하고, 객체의 위치, 크기 정보, 모양 분석, ROI 추출 등이 가능하다. 이 때 사용할 수 있는 기법 중의 하나가 레이블링(labeling)이다.

레이블링의 이해

일단 배경과 객체를 구분하고 나면 이제 다시 각각의 객체를 구분하고 분석하는 작업이 필요하다. 레이블링은 서로 연결되어 있는 객체 픽셀에 고유번호를 할당하여 영역 기반 모양 분석, 레이블맵, 바운딩 박스, 픽셀 개수, 무게 중심 좌표 등을 반환할 수 있게 해준다.

객체 픽셀 집합에 고유 번호를 매기는 작업은 연결된 구성 요소 레이블링 (connected components labeling) 이라고도 불린다.

레이블링은 일반적으로 이진화된 영상에서 수행하며, 입력 영상의 픽셀 값이 0이면 배경, 아니면 객체 픽셀로 인식한다. 그리고 객체는 한 개 이상의 인접한 픽셀로 이루어지며, 하나의 객체를 구성하는 모든 픽셀에는 같은 레이블 번호가 지정된다.

픽셀 연결 관계

이웃한 픽셀의 연결 관계는 4-방향 연결성(4-way connectivity) / 8-방향 연결성(8-way connectivity)로 정의된다. 4방향은 상하좌우로만 연결되며 8방향은 대각선 인접 픽셀들도 연결되어 있다고 간주한다.

img

레이블 맵 (label map)

영상의 레이블링을 수행하면 각각의 객체 영역에 고유 번호가 매겨진 2차원 정수 행렬이 만들어진다. 이 행렬을 레이블 맵이라고 부르며, 레이블링 알고리즘은 다양하지만 모두 같은 형태의 레이블 맵을 생성한다.

img

레이블링 함수

cv2.connectedComponents(src, connectivity, ltype) → retval, labels

  • src: 8비트 1채널 영상
  • connectivity: 4 또는 8, 기본값은 8
  • ltype: labels 타입. 기본값은 cv2.CV_32S (32bit signed integer)
  • retval: 객체 개수(레이블 개수) N 반환. 카운팅은 0부터하는데 0은 배경객체이므로 실제 객체 개수는 N-1개
  • labels: 레이블 맵 행렬

위 함수만으로 레이블맵을 만들 수 있으나, 보통 레이블링 수행 후 각 객체 영역이 어느 위치에 어느 정도의 크기로 존재하는지 확인이 필요하다. 그래서 아래의 응용 레이블링 함수를 사용한다.

cv2.connectedComponentsWithStats(src, connectivity, ltype) → retval, labels, stats, centroids

  • 기본적인 파라미터와 입/출력 데이터 타입은 connectedComponents() 와 동일
  • stats: 추출된 객체의 위치, 가로세로 길이, 면적 등의 정보 행렬
  • centroids: 객체들의 무게중심 정보

img

stats 행렬의 각 행은 N번째 객체 정보를 담고 있고, 각 행 내에는 [객체를 감싸는 바운딩 박스의 x좌표 시작점, 바운딩 박스의 y좌표 시작점, 객체 가로 크기, 객체 세로 크기, 객체의 총 픽셀 개수] 가 저장되어 있다.

centroids 행렬에는 각 행이 N번째 객체의 무게 중심 좌표 (x, y)를 담고 있다. 무게 중심은 객체의 모든 픽셀의 x좌표를 더한 값을 픽셀 개수로 나눈 값과 y좌표를 더한 값을 픽셀 개수로 나눈 값으로 구한다.

src = cv2.imread('img/keyboard.bmp', cv2.IMREAD_GRAYSCALE)
src = cv2.GaussianBlur(src, (3,3), 2)  # 노이즈 제거
_, src_bin = cv2.threshold(src, 0, 255, cv2.THRESH_OTSU)  # 영상 이진화

cnt, labels, stats, centroids = cv2.connectedComponentsWithStats(src_bin)

dst = cv2.cvtColor(src, cv2.COLOR_GRAY2BGR)

for i in range(1, cnt):
    x, y, w, h, area = stats[i]
    cv2.rectangle(dst, (x, y), (x+w, y+h), (0, 255, 255))

cv2.imshow('src', src)
cv2.imshow('src_bin', src_bin)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

img

댓글남기기