OpenCV / / 2022. 11. 14. 13:01

OpenCV - 레이블링 기법

 

<레이블링의 이해> 
번호를 매겨준다.

-배경과 객체를 구분한후 레이블링을 이용하여 객체간 구분
-연결 구성 요소 레이블링(CCL)
--> 객체 인식을 위한 전처리 과정으로 사용
--> 이진화 영상에서 수행( 배경: 검은색 / 객체: 흰색)
--> 연결성 정의에 따라 결과가 달라질 수 있음
''''''
<고전적 레이블링 기법>

-등가 테이블을 만들면서 영상을 두 번 스캔함으로써 레이블링을 수행
-첫번째 스캔에서는 레이블을 전파 시키면서 등가 테이블을 생성
-두번째 스캔에서는 등가 테이블을 참조하여 각 픽셀에 고유의 레이블을 부여
-이웃 연결성 고려
-임의의 위치에서 위쪽과 왼쪽 두 이웃 픽셀을 조사하여
 
[두 이웃 픽셀에 레이블이 존재하지 않는 경우, ]
--> 새로운 레이블을 지정하고,
--> 자기 자신의 레이블을 가리키는 새 등가 테이블 항목을 생성한다.

[두 이웃 픽셀 중 하나에만 레이블이 존재하는 경우]
-->이웃 픽셀과 동일한 레이블을 지정한다.

[두 이웃 픽셀 모두 레이블이 존재 하고, 서로 동일한 레이블일 경우]
-->이웃 픽셀과 동일한 레이블을 지정한다.

[두 이웃 픽셀 모두에 레이블이 존재하며, 서로 다른 레이블인 경우]
-->두 레이블 중 작은번호의 레이블을 지정하고,
-->두 레이블 중 큰 번호의 레이블이 작은 번호의 레이블을 가리키도록 등가 테이블을 조정한다.

''''''
''''''
구현
-OpenCV 함수

cv2.CONNECTEDCOMPONENTS(image[,LABELS[,CONNECTIVITY[,ITYPE]]]):
연결된 COMPONENTS의 개수를 반환하고 라벨링 해준다.

[파라미터]
 
image: INPUT
LABELS : OUTPUT
CONNECTIVITY : 4 or 8 이웃 연결성

라벨링 실습
'''
import cv2
import numpy as np
# Circle 영상에 컨버트 칼라와 쓰레스홀드를 주었다.
src = cv2.imread('./circles.jpg')
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
ret, res = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY_INV) # Thresh binary inverse를 걸었다.
# 그래서 검은게 하얀색으로 하얀게 검은색으로 바뀌었다.
cv2.imshow('src', src)
cv2.imshow('res', res)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.waitKey(1)
# 이 CCL 적용하면 우리가 원하는 것은 1, 2, 3 레이블링 하는 것, 컴포넌트 레이블링을 한다.

ret, labels = cv2.connectedComponents(res)
print('ret=', ret)
print('labels', np.unique(labels))
labels = cv2.normalize(src=labels, dst=labels, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
print('norm labels', np.unique(labels))
cv2.imshow('src', src)
cv2.imshow('labels', labels)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.waitKey(1)
# 이건 그냥 커넥티드 컴포넌트를 한 것이므로 이거 보다는 아래에 있는 것을 하는 게 낫지 않을까
# 이걸 하게 되면 바로 끝이 난다. 영역과 무게 중심을 다 찾아 준다.
ret, labels, stats, centroids = cv2.connectedComponentsWithStats(res)
print('ret=', ret)
print('labels=', np.unique(labels))
print('stats=', stats)
print('centroids=', centroids)
dst = src.copy()
cv2.circle(dst, (int(centroids[0][0]), int(centroids[0][1])), radius=5, color=(255,0,0), thickness=-1)
cv2.circle(dst, (int(centroids[1][0]), int(centroids[1][1])), radius=3, color=(0,0,255), thickness=-1)
cv2.circle(dst, (int(centroids[2][0]), int(centroids[2][1])), radius=3, color=(0,0,255), thickness=-1)
cv2.circle(dst, (int(centroids[3][0]), int(centroids[3][1])), radius=3, color=(0,0,255), thickness=-1)
cv2.rectangle(dst, (stats[0][0], stats[0][1]), (stats[0][0]+stats[0][2], stats[0][1]+stats[0][3]), [255,0,0], 5)
cv2.rectangle(dst, (stats[1][0], stats[1][1]), (stats[1][0]+stats[1][2], stats[1][1]+stats[1][3]), [0,0,255])
cv2.rectangle(dst, (stats[2][0], stats[2][1]), (stats[2][0]+stats[2][2], stats[2][1]+stats[2][3]), [0,0,255])
cv2.rectangle(dst, (stats[3][0], stats[3][1]), (stats[3][0]+stats[3][2], stats[3][1]+stats[3][3]), [0,0,255])
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(dst, 'label=1', (stats[1][0], stats[1][1]), font, 0.5, (255, 0, 0), 1)
cv2.putText(dst, 'label=2', (stats[2][0], stats[2][1]), font, 0.5, (255, 0, 0), 1)
cv2.putText(dst, 'label=3', (stats[3][0], stats[3][1]), font, 0.5, (255, 0, 0), 1)
cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.waitKey(1)

 

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유