PYTHON 프로그래밍

본문 바로가기
사이트 내 전체검색


PYTHON 프로그래밍
PYTHON 프로그래밍

21. 윤곽선 검출

페이지 정보

작성자 관리자 댓글 0건 조회 3,875회 작성일 19-09-28 23:09

본문

21. 윤곽선 검출

윤곽선(Contour)


영상이나 이미지의 윤곽선(컨투어)을 검출하기 위해 사용합니다.

영상이나 이미지에서 외곽과 내곽의 윤곽선(컨투어)을 검출할 수 있습니다.


소스 :


import cv2

src = cv2.imread("image/contours.jpg", cv2.IMREAD_COLOR)

gray = cv2.cvtColor(src, cv2.COLOR_RGB2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
binary = cv2.bitwise_not(binary)

contours, hierachy = cv2.findContours(binary, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)

for i in range(len(contours)):
    cv2.drawContours(src, [contours[i]], 0, (0, 0, 255), 2)
    cv2.putText(src, str(i), tuple(contours[i][0][0]), cv2.FONT_HERSHEY_COMPLEX, 0.8, (0, 255, 0), 1)
    print(i, hierachy[0][i])
    cv2.imshow("src", src)
    cv2.waitKey(0)

cv2.destroyAllWindows()


설명 :


gray = cv2.cvtColor(src, cv2.COLOR_RGB2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
binary = cv2.bitwise_not(binary)

윤곽선(컨투어)를 검출하는 주된 요소는 하얀색의 객체를 검출합니다.

그러므로 배경은 검은색이며 검출하려는 물체는 하얀색의 성질을 띄게끔 변형합니다.

이진화 처리 후, 반전시켜 검출하려는 물체를 하얀색의 성질을 띄도록 변환합니다.

 


contours, hierachy = cv2.findContours(binary, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)

cv2.findContours()를 이용하여 이진화 이미지에서 윤곽선(컨투어)를 검색합니다.

cv2.findContours(이진화 이미지, 검색 방법, 근사화 방법)을 의미합니다.

반환값으로 윤곽선, 계층 구조를 반환합니다.

윤곽선은 Numpy 구조의 배열로 검출된 윤곽선의 지점들이 담겨있습니다.

계층 구조는 윤곽선의 계층 구조를 의미합니다. 각 윤곽선에 해당하는 속성 정보들이 담겨있습니다.

 


for i in range(len(contours)):
    cv2.drawContours(src, [contours[i]], 0, (0, 0, 255), 2)
    cv2.putText(src, str(i), tuple(contours[i][0][0]), cv2.FONT_HERSHEY_COMPLEX, 0.8, (0, 255, 0), 1)
    print(i, hierachy[0][i])
    cv2.imshow("src", src)
    cv2.waitKey(0)

반복문을 사용하여 검출된 윤곽선을 그리며 해당 윤곽선의 계층 구조를 표시합니다.

cv2.drawContours()을 이용하여 검출된 윤곽선을 그립니다.

cv2.drawContours(이미지, [윤곽선], 윤곽선 인덱스, (B, G, R), 두께, 선형 타입)을 의미합니다.

윤곽선은 검출된 윤곽선들이 저장된 Numpy 배열입니다.

윤곽선 인덱스는 검출된 윤곽선 배열에서 몇 번째 인덱스의 윤곽선을 그릴지를 의미합니다.

윤곽선 인덱스를 0으로 사용할 경우 0 번째 인덱스의 윤곽선을 그리게 됩니다. 하지만, 윤곽선 인수를 대괄호로 다시 묶을 경우, 0 번째 인덱스가 최댓값인 배열로 변경됩니다.


동일한 방식으로 [윤곽선], 0과 윤곽선, -1은 동일한 의미를 갖습니다. (-1은 윤곽선 배열 모두를 의미)


검색 방법

 

cv2.RETR_EXTERNAL : 외곽 윤곽선만 검출하며, 계층 구조를 구성하지 않습니다.

cv2.RETR_LIST : 모든 윤곽선을 검출하며, 계층 구조를 구성하지 않습니다.

cv2.RETR_CCOMP : 모든 윤곽선을 검출하며, 계층 구조는 2단계로 구성합니다.

cv2.RETR_TREE : 모든 윤곽선을 검출하며, 계층 구조를 모두 형성합니다. (Tree 구조)

 

 

근사화 방법

 

cv2.CHAIN_APPROX_NONE : 윤곽점들의 모든 점을 반환합니다.

cv2.CHAIN_APPROX_SIMPLE : 윤곽점들 단순화 수평, 수직 및 대각선 요소를 압축하고 끝점만 남겨 둡니다.

cv2.CHAIN_APPROX_TC89_L1 : 프리먼 체인 코드에서의 윤곽선으로 적용합니다.

cv2.CHAIN_APPROX_TC89_KCOS : 프리먼 체인 코드에서의 윤곽선으로 적용합니다.

 

 

계층 구조

 

계층 구조는 윤곽선을 포함 관계의 여부를 나타냅니다.

즉, 외곽 윤곽선, 내곽 윤곽선, 같은 계층 구조를 구별할 수 있습니다.

이 정보는 hierachy에 담겨있습니다.

hierachy를 출력할 경우 다음과 같은 결과를 반환합니다.

[[[ 2 -1  1 -1]
  [-1 -1 -1  0]
  [ 4  0  3 -1]
  [-1 -1 -1  2]
  [ 6  2  5 -1]
  [-1 -1 -1  4]
  [ 8  4  7 -1]
  [-1 -1 -1  6]
  [ 9  6 -1 -1]
  [10  8 -1 -1]
  [11  9 -1 -1]
  [-1 10 -1 -1]]]

첫 번째 계층 구조는 [ 2 -1 1 -1]의 값을 갖습니다.

[다음 윤곽선, 이전 윤곽선, 내곽 윤곽선, 외곽 윤곽선]에 대한 인덱스 정보를 포함하고 있습니다.

인덱스 0의 윤곽선의 다음 윤곽선은 인덱스 2의 윤곽선을 의미하며 이전 윤곽선은 존재하지 않다는 것을 의미합니다.

내곽 윤곽선은 인덱스 1에 해당하는 윤곽선을 자식 윤곽선으로 두고 있다는 의미입니다.

즉, 인덱스 0 윤곽선 내부에 인덱스 1의 윤곽선이 포함되어 있습니다.

외곽 윤곽선은 -1의 값을 갖고 있으므로 외곽 윤곽선은 존재하지 않습니다.

다음 검출 결과를 통하여 쉽게 이해할 수 있습니다.

1.JPG 


0 [ 2 -1  1 -1]
1 [-1 -1 -1  0]
2 [ 4  0  3 -1]

print(i, hierachy[0][i])을 통하여 3개의 윤곽선을 출력한 결과입니다.

다음 윤곽선과 이전 윤곽선의 정보가 -1의 값이 아니라면 서로 동등한 계층의 윤곽선입니다.

0번 인덱스의 윤곽선과 동등한 계층에 있는 윤곽선은 2번 인덱스의 윤곽선입니다.

0번 인덱스의 윤곽선은 1번 인덱스의 윤곽선을 내부 윤곽선으로 갖고 있습니다.

1번 인덱스의 윤곽선은 동등한 계층에 있는 윤곽선이 없으므로 다음 윤곽선과 이전 윤곽선의 값이 -1입니다.

1번 인덱스의 윤곽선은 내곽 윤곽선이 없으며, 외곽 윤곽선만 존재하여 0번 인덱스의 윤곽선을 외곽 윤곽선으로 반환합니다.

해당 예제는 cv2.RETR_CCOMP로 2 단계 계층 구조로만 표시합니다.


계층 구조를 사용하여 내곽, 외곽 윤곽선을 구분할 수 있습니다.

 

결과 :


 

contours.jpg 

2.JPG 

댓글목록

등록된 댓글이 없습니다.


개인정보취급방침 서비스이용약관 모바일 버전으로 보기 상단으로

TEL. 063-469-4551 FAX. 063-469-4560 전북 군산시 대학로 558
군산대학교 컴퓨터정보공학과

Copyright © www.leelab.co.kr. All rights reserved.