12장. Contour Detection 과 객체 분석
cv2.findContours 의 입력과 결과
운동장 둘레에 하얀 선을 긋는 사람을 떠올려 봅시다. 선 긋는 사람은 운동장 가장자리에 서서 한 발짝씩 옮기며 발자국을 남깁니다. 한 바퀴를 돌아 출발점에 오면 일이 끝납니다. 남은 것은 발자국의 좌표 목록입니다. cv2.findContours 가 흰 덩어리마다 이 일을 합니다.
그림의 네 단계가 윤곽선을 얻는 순서입니다. 흑백으로 읽고, 물체가 흰색이 되게 이진화하고, cv2.findContours 로 흰 덩어리의 테두리를 따라간 뒤, 물체마다 점 배열 하나씩을 얻습니다. 여기서 운동장이 흰 덩어리, 선 긋는 사람의 발자국이 윤곽선의 점, 한 바퀴 돈 발자국 목록이 윤곽선 하나입니다.
가로 9칸, 세로 7칸짜리 작은 그림에서 찾은 윤곽선입니다. 다홍 점은 테두리 칸이고, 점 안의 번호가 배열에 담긴 순서입니다. 왼쪽 위 칸(1, 1)에서 출발해 테두리를 한 바퀴 돌고 출발점 옆에서 끝납니다. 점은 흰 덩어리 바깥이 아니라 가장자리의 흰 칸 위에 놓입니다.
인자와 돌려주는 값
| 구분 | 이름 | 뜻 |
|---|---|---|
| 인자 1 | image | 8비트 흑백 그림. 0 이 아닌 칸을 모두 흰색(물체)으로 본다 |
| 인자 2 | mode | 찾는 방식. cv2.RETR_EXTERNAL, cv2.RETR_LIST, cv2.RETR_TREE 등 |
| 인자 3 | method | 점을 담는 방식. cv2.CHAIN_APPROX_NONE, cv2.CHAIN_APPROX_SIMPLE |
| 돌려주는 값 1 | contours | 윤곽선 목록(튜플). 윤곽선 하나는 (점 수, 1, 2) 모양의 배열 |
| 돌려주는 값 2 | hierarchy | 계층 구조. (1, 윤곽선 수, 4) 모양의 배열 |
윤곽선 배열의 모양 (점 수, 1, 2)
윤곽선 하나는 점 수만큼의 줄이 있고, 줄마다 [x, y] 좌표가 들어 있습니다. 가운데의 1 은 OpenCV 가 점 배열을 담는 옛 방식에서 남은 칸이라 늘 1 입니다. 좌표만 보고 싶으면 reshape(-1, 2) 로 (점 수, 2) 모양으로 펼칩니다.
| 모양의 자리 | 값의 예 | 뜻 |
|---|---|---|
| 첫째 | 4 | 점의 수 |
| 둘째 | 1 | 늘 1 (옛 방식의 흔적) |
| 셋째 | 2 | x 좌표와 y 좌표. 그림의 배열 번호 [y, x] 와 순서가 반대다 |
짧은 예시
import cv2
shapes = cv2.imread("ch12_shapes.png", cv2.IMREAD_GRAYSCALE)
contours, hierarchy = cv2.findContours(shapes, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
print("contours 의 자료형:", type(contours).__name__, "/ 길이:", len(contours))
print("hierarchy 의 모양:", hierarchy.shape)
# 가장 마지막 윤곽선(곧은 네모)의 모양과 점 좌표
last = contours[-1]
print("마지막 윤곽선의 모양:", last.shape)
print("점 좌표 [x, y]:", last.reshape(-1, 2).tolist())교안 PC 에서는 자료형이 tuple, 길이 8, hierarchy 의 모양이 (1, 8, 4) 입니다. 마지막 윤곽선은 (4, 1, 2) 모양이고 점이 [[20, 20], [20, 69], [99, 69], [99, 20]] 입니다. 그림을 그릴 때 네모의 왼쪽 위를 (20, 20), 오른쪽 아래를 (99, 69) 로 칠했으므로 꼭짓점 칸이 그대로 나왔습니다.
주의할 점
- 입력은 흰 물체, 검은 바탕이어야 합니다. 바탕이 흰 그림을 그대로 넣으면 그림 전체가 덩어리 하나로 잡힙니다.
- 윤곽선이 담긴 순서는 왼쪽 위부터가 아닙니다. 이 그림에서는 아래쪽 물체가 앞 번호를 받았습니다. 번호를 붙여 보고할 때는 "분석 결과를 표로 정리하기" 절처럼 위치로 다시 정렬합니다.
- OpenCV 3.x 의 일부 판은 값을 세 개 돌려주었습니다. 이 과정의 OpenCV 5.0 은 두 개(contours, hierarchy)입니다.