외곽선 검출이란?
- 객체의 외곽선 좌표를 모두 추출하는 작업. Boundary tracking. Contour tracing.
- 바깥쪽 & 안쪽(홀) 외곽선 → 외곽선의 계층 구조도 표현 가능
외곽선 객체 하나의 표현 방법
- numpy.ndarray
- shape=(K, 1, 2) (K는 외곽선 좌표 개수)
- dtype=numpy.int32
여러 외곽선 표현 방법
- "객체 하나의 외곽선(numpy.ndarray)"을 원소로 갖는 리스트
- len(리스트) = 전체 외곽선 개수(N)
외곽선 검출 함수
cv2.findContours(image, mode, method, contours=None, hierarchy=None, offset=None) -> contours, hierarchy
- image : 입력 영상. non-zero 픽셀을 객체로 간주함.
- mode : 외곽선 검출 모드. cv2.RETR_로 시작하는 상수.
- method : 외곽선 근사화 방법. cv2.CHAIN_APPROX_로 시작하는 상수.
- contours : 검출된 외곽선 좌표. numpy.ndarray로 구성된 리스트. len(contours)=전체 외곽선 개수(N).
- contours[i].shape=(K, 1, 2)
- contours[i].dtype=numpy.int32
- hierarchy : 외곽선 계층 정보.
- numpy.ndarray.shape=(1, N, 4), dtype=numpy.int32
- hierrarchy[0, i, 0] ~ hierarchy[0, i, 3]이 순서대로 next, prev, child, paraent 외곽선 인덱스를 가리킴. 해당 외곽선이 없으면 -1.
- offset : 좌표 값 이동 옵셋. 기본값은 (0, 0)
외곽선 그리기
cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None) -> image
- image : 입출력 영상
- contours : (cv2.findContours() 함수로 구현) 외곽선 좌표 정보
- contourIdx : 외곽선 인덱스. 음수(-1)를 지정하면 모든 외곽선을 그린다.
- color : 외곽선 색상
- thickness : 외곽선 두께. thickness < 0이면 내부를 채운다.
- lineType : LINE_4, LINE_8, LINE_AA 중 하나 지정
- hierarchy : 외곽선 계층 정보
- maxLevel : 그리기를 수행할 최대 외곽선 레벨. maxLevel=0이면 contourIdx로 지정된 외곽선만 그린다.
계층 정보를 사용하는 외곽선 검출 예제
src = cv2.imread('contours.bmp', cv2.IMREAD_GRAYSCALE)
contours, hier = cv2.findContours(src, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
dst = cv2.cvtColor(src, cv2.COLOR_GRAY2BGR)
idx = 0
while idx >= 0:
c = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
cv2.drawContours(dst, contours, idx, c, 2, cv2.LINE_8, hier)
idx = kier[0, idx, 0]
계층 정보를 사용하지 않는 외곽선 검출 예제
src = cv2.imread('milkdrop.bmp', cv2.IMREAD_GRAYSCALE)
_, src_bin = cv2.threshold(src, 0, 255, cv2.THRESH_OTSU)
contours, _ = cv2.findContours(src_bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
h, w = src.shape[:2]
dst = np.zeros((h, w, 3), np.uint8)
for i in range(len(contours)):
c = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
cv2.drawContours(dst, contours, i, c, 1, cv2.LINE_AA)