12장. Contour Detection 과 객체 분석
윤곽선 그리기
색칠 공부 책의 테두리를 색연필로 덧그린다고 해 봅시다. 먼저 어떤 그림 위에 그릴지 고르고, 덧그릴 테두리를 고르고, 색연필의 색과 굵기를 고릅니다. 테두리 안을 꽉 칠할 수도 있습니다. cv2.drawContours 가 받는 인자도 이 순서입니다.
초록 상자처럼 흑백 그림에 색을 칠하려면 먼저 cv2.COLOR_GRAY2BGR 로 채널 세 개짜리 그림을 만듭니다. 다홍 상자의 번호는 -1 이면 모든 윤곽선을, 0, 1, 2 처럼 주면 그 번호 하나만 그립니다. 보라 상자의 두께는 선의 굵기이고, -1 을 주면 안을 채웁니다. 여기서 도화지가 그림, 덧그릴 테두리가 번호, 색연필이 색과 두께입니다.
왼쪽은 모든 윤곽선을 빨간 선으로, 가운데는 7번(곧은 네모) 하나만, 오른쪽은 모든 윤곽선의 안을 초록으로 채웠습니다. 오른쪽에서 도넛의 구멍까지 채워진 것은 EXTERNAL 로 바깥 윤곽선만 찾았기 때문입니다.
인자 다섯 개
| 순서 | 이름 | 예 | 뜻 |
|---|---|---|---|
| 1 | image | canvas | 그릴 그림. 이 그림이 바로 바뀐다 |
| 2 | contours | contours | 윤곽선 목록. 하나만 그릴 때도 목록째 준다 |
| 3 | contourIdx | -1 | 그릴 번호. -1 이면 모두 |
| 4 | color | (0, 0, 255) | 색. B, G, R 순서라 빨강 |
| 5 | thickness | 2 | 선 두께. -1 이면 안을 채운다 |
짧은 예시
import cv2
shapes = cv2.imread("ch12_shapes.png", cv2.IMREAD_GRAYSCALE)
contours, _ = cv2.findContours(shapes, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# GRAY2BGR: 흑백(1채널)을 같은 밝기의 컬러(3채널)로 바꾼다. 색을 칠하려면 필요하다
canvas = cv2.cvtColor(shapes, cv2.COLOR_GRAY2BGR)
cv2.drawContours(canvas, contours, -1, (0, 0, 255), 2) # 모두, 빨강, 두께 2
print("그린 그림의 모양:", canvas.shape)
# 채운 판으로 바꾸면 윤곽선이 둘러싼 칸이 모두 255 인 마스크가 된다
mask = cv2.drawContours(shapes * 0, contours, -1, 255, -1)
print("채운 칸 수:", int((mask > 0).sum()), "/ 원래 흰 칸 수:", int((shapes > 0).sum()))교안 PC 에서는 모양이 (240, 320, 3) 이고, 채운 칸이 21,861개, 원래 흰 칸이 20,604개입니다. 차이 1,257칸은 도넛의 구멍(반지름 20, 3.14 × 20 × 20 = 1,256)입니다. 바깥 윤곽선의 안을 채우면 구멍도 메워지기 때문입니다.
주의할 점
cv2.drawContours는 넣은 그림을 바로 고칩니다. 원본을 남기려면.copy()나cvtColor로 만든 새 그림에 그립니다.- 윤곽선 하나만 그릴 때
cv2.drawContours(img, contours[3], ...)처럼 배열 하나를 넣으면 점마다 윤곽선으로 보아 점만 찍힙니다.contours와 번호 3을 주거나[contours[3]]처럼 목록에 넣어 줍니다.