본문으로 바로가기

파이썬 OpenCV 라벨링(Labeling)

category OpenCV 2020. 7. 26. 19:29

Labeling

라벨링은 이진화된 이미지에서 연결되어 있는 픽셀들을 Grouping 하는 작업입니다.

connectedComponentsWithStats 를 사용합니다.

 

cv2.connectedComponentsWithStats(src, labels=None, stats=None, centroids=None, connectivity=None, ltype=None) -> retval, labels, stats, centroids

  • src: 입력 이미지 (grayscale)
  • labels: 레이블 맵 행렬(numpy.ndarray, src 와 동일 타입)
  • stats: connected components 를 감싸는 직사각형(bounding box) 및 픽셀 정보를 담고 있음
  • centroids: 각 connected components 의 무게중심 위치
  • ltype: labels 의 데이터타입 (default: cv2.CV_32S)
import os
import cv2
import numpy as np

path = os.path.join('img', 'keyboard.jpeg')

src = cv2.imread(path)
src = cv2.resize(src, None, fx=1.5,  fy=1.5)
dst = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)

# _, th = cv2.threshold(dst, 0, 255, cv2.THRESH_OTSU)
_, th = cv2.threshold(dst, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)
dst = cv2.cvtColor(th, cv2.COLOR_GRAY2BGR)

_, labels, stats, centroids = cv2.connectedComponentsWithStats(th)
print(stats)

for x, y, w, h, cnt in stats:
    if (h, w) < dst.shape:
        cv2.rectangle(dst, (x, y, w, h), (0, 255, 0), 1)

cv2.imshow('src', src)
cv2.imshow('th', th)
cv2.imshow('dst', dst)

cv2.waitKey()
cv2.destroyAllWindows()

원본

threshold 를 사용하여 이진화를 했습니다.

잘보이게 하기 위해 cv2.THRESH_BINARY_INV 을 사용했구요.

# _, th = cv2.threshold(dst, 0, 255, cv2.THRESH_OTSU)
_, th = cv2.threshold(dst, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)

 

statsx좌표, y좌표, width, height, 개수 정보를 가지고 있습니다.

_, labels, stats, centroids = cv2.connectedComponentsWithStats(th)
print(stats)
[[     0      0   1329    388 461207]
 [    54     15     53     53    391]
 [   135     15     53     53    390]
 ...
 [   971    311      1      1      1]
 [  1017    311      5      1      5]
 [   968    314      5      4     13]]

 

다음과 같이 stats의 정보를 이용하여 직사각형을 그립니다.

for x, y, w, h, cnt in stats:
    if (h, w) < dst.shape:
        cv2.rectangle(dst, (x, y, w, h), (0, 255, 0), 1)