Program/OPEN_CV

[Open CV] 이진 영상 처리 _ 외곽선 검출

사막여유 2022. 6. 10. 08:28
728x90

 

레이블링과 더불어 영상을 객체단위로 분석할 때 사용할 수 있는 외곽선 검출에대해 알아본다.

 

외곽선 검출이란?

 - 객체의 외곽선 좌표를 모두 추출하는 작업. Boundary tracking. Contour tracing

 - 옵션에 따라 바깥쪽 또는 안쪽 또는 모든 (홀) 외곽선 -> 외곽선의 계층 구조도 표현 가능
   계층구조 : 외곽선 바깥에 다른 외곽선이 있다면 어떤 순서로 있는지에대한 정보 등...

 

외곽선 객체 하나의 표현 방법

 - numpy.ndarray

 - shape = ( K, 1, 2 ) ( K는 외곽선 좌표 개수 )
   3차원 행렬, K는 외곽선 좌표들의 개수, 1은고정, 2는 X , Y 좌표를 표현

 - dtype = numpy.int32 ( 4byte 정수형태 )

 


외곽선 검출 함수

cv2.findContours ( image, mode, method, contours, hierarchy, offset ) -> contours, hierarchy

image : 입력 영상. non-zero 픽셀을 객체로 간주함
             보통 이진영상을 입력으로 주게되고 객체의 외곽선을 검출

mode : 외곽선 검출 모드 , cv2.RETR_로 시작하는 상수
            아래 이미지를 보게되면 어떤 mode로 하는지에 따라 입력영상에대한 외곽선을 어떻게 검출할지가
            나뉘게 된다.
            ( EXTERNAL, LIST, CCOMP, TREE )

 * EXTERNAL : 검정색 배경에서 만나게되는 첫번째 흰색 객체 즉, 바깥쪽 외곽선만 검출하게된다.

 * LIST : 바깥쪽 안쪽의 모든 외곽선들을 찾는다.

 * CCOMP : 계층구조를 만들어준다.
                   부모계층을 기준으로 자식계층을 구분하되, 자식들 내부에 다른 윤곽선이 있으면
                   해당 자식들을 부모계층으로 같이 올려준다.
                   ( 또한 자세히보면 양방향 화살표는 자식 한개만 주게되는 것을 볼 수 있는데
                     Child 는 대표값 하나만 

 * TREE : 계층구조를 만들어준다.
               실제 위 이미지를 보면 부모계층을 기준으로 자식계층이 구분되는것을 볼 수 있다.

 

method : 외곽선 근사화 방법. cv2.CHAIN_APPROX_로 시작하는 상수

 * cv2.CHAIN_APPROX_NONE : 근사화 없음
( 검출된 모든 외곽선 좌표를 반환 )

 * cv2.CHAIN_APPROX_SIMPLE : 수직선, 수평선, 대각선에 대해 끝점만 저장
( 단순한 형태로 외곽선 좌표를 반환 )

 

contours : 검출된 외곽선 좌표. numpy.ndarray로 구성된 리스트.
                 lens(contours) = 전체 외곽선 개수 ( N )

hierarchy : 외곽선 계층 정보. numpy.ndarray.shape ( 1,N,4 ). dtype = numpy.int32
                  hierarchy[0,i,0] ~ hierarchy[0,i,3] 이 순서대로 next,prev,child,parent 외곽선을 가리킴
                  해당 외곽선이 없으면 -1

offset : 좌표 값 이동 옵셋 . 기본값은 ( 0 , 0 )


외곽선 그리기

cv2.drawContours ( image, contours, contourIdx, color, thickness, lineType, hierarachy, maxLevel,                                      offset ) -> image

image : 입출력 영상

contours : (cv2.findContours() 함수로 구한 ) 회곽선 좌표 정보

contourIdx : 외곽선 인덱스. 음수 ( -1 )를 지정하면 모든 외곽선을 그린다.

color : 외곽선 색상

thickness : 외곽선 두께. thikness < 0이면 내부를 채운다.

lineType : LINE_4, LINE_8, LINE_AA 중 하나 지정

hierarchy : 외곽선 계층 정보.

maxLevel : 그리기를 수행할 최대 외곽선 레벨. maxLevel = 0이면 contourIdx로 지정된 외곽선만 그린다.


위 외곽선 검출 함수와 외곽선 그리기 함수를 사용하여 실제 외곽선 검출을 본다.

 

실제 이 부분에서 잘 봐야 하는 곳이 while 루프 부분이다.

c 변수에는 랜덤한 색상값을 주었고, idx 업데이트는 hier의 정보를 사용한다.

 * 위 설명중 ( hierarchy[0,i,0] ~ hierarchy[0,i,3] 이 순서대로 next,prev,child,parent 외곽선을 가리킴 )
   을 참고하면 hier는 객체 외곽선 번호정보이고 [ 0 , i , 0 ] 를 보면 next 정보인 것을 알 수 있다.

현재와 같은 설정이면 위 이미지의 0 , 4 , 6 의 순서대로 윤곽선이 검출된다. 

 

하지만 위 영상을 보면 내부 윤곽선까지 모두 검출되는 것을 볼 수 있다.

이는 drawContours 에서 마지막 인자에 hier 인자를 넣어서 나오는 현상이다.

실제로 drawContours 에서 hier 인자를 없애고 다시 Contour 를 진행하게 되면

바깥쪽 윤곽선만 표시되는 것을 볼 수 있다.

 

TREE를 사용해서 위 아래 객체를 위객체 , 아래객체로만 분리하여 객체검출을 할수도 있다.

물론 draw에서 hier 인자를 삭제하면 바깥쪽 외곽선만 검출할 수 있다.

 

실제로는 검출된 외곽선 좌표들을 이용해서 내가 찾고자하는 특정한 객체가 맞는지 특정한 객체 영역을 따로

잘라내는 용도로도 사용될 수 있다.

findContour 함수를 조금 더 공부하면 알 수 있다.

 

 

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.

https://bit.ly/3L3avNW

 

패스트캠퍼스 [직장인 실무교육]

프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.

fastcampus.co.kr

728x90