OpenCV 비전 실무13장 · Shape 분석과 ROI 처리4 / 21← 이전목차다음 →MetaContents

13장. Shape 분석과 ROI 처리

근사 다각형

지도에서 구불구불한 해안선을 손으로 따라 그린다고 해 봅시다. 작은 굴곡까지 다 그리려면 끝이 없습니다. 그래서 "1cm 안쪽의 굴곡은 무시하고 곧은 선으로 긋자"고 정하면, 해안선이 꼭짓점 몇 개짜리 다각형이 됩니다. 무시하는 폭을 넓히면 꼭짓점이 더 줄어듭니다. cv2.approxPolyDP 가 이 일을 합니다.

윤곽선, 둘레 재기, epsilon 정하기, 꼭짓점 세기의 네 단계 흐름도

그림의 네 단계를 따라 꼭짓점을 셉니다. 윤곽선의 둘레를 재고, 둘레에 비율(예: 0.01)을 곱해 epsilon 을 정하고, approxPolyDP 가 돌려준 점의 개수를 셉니다. 여기서 해안선이 윤곽선이고, "1cm 안쪽은 무시"의 1cm 가 epsilon 입니다.

원과 별의 윤곽선을 epsilon 비율 0.005, 0.02, 0.08 로 근사한 다각형을 겹쳐 그린 그림

위 줄은 원, 아래 줄은 별입니다. 다홍 선이 근사 다각형이고, 점이 꼭짓점입니다. 비율 0.005 에서 원은 꼭짓점 16개로 거의 원 그대로이고, 0.02 에서는 8개, 0.08 에서는 4개로 네모가 됩니다. 별은 0.005 와 0.02 에서 모두 10개(뾰족한 끝 5개와 안쪽 꺾임 5개)를 지키다가 0.08 에서 5개가 됩니다. 곧은 변으로 된 모양은 꼭짓점 수가 잘 바뀌지 않고, 둥근 모양은 epsilon 에 따라 크게 바뀝니다.

epsilon 을 둘레의 비율로 주는 까닭

epsilon 은 "곧은 선에서 이만큼까지 비뚤어져도 곧은 선으로 본다"는 칸 수입니다. 그런데 큰 물체와 작은 물체에 같은 칸 수를 주면 결과가 달라집니다. 둘레 400 인 큰 원에서 2칸은 작은 굴곡이지만, 둘레 40 인 작은 원에서 2칸은 큰 굴곡입니다. 그래서 둘레에 비율을 곱해 정합니다.

비율원(둘레 178.5)의 epsilon원의 꼭짓점별의 꼭짓점쓰임
0.005178.5 × 0.005 ≈ 0.9칸1610작은 굴곡까지 남긴다
0.01178.5 × 0.01 ≈ 1.8칸1210이 장의 기본값
0.02178.5 × 0.02 ≈ 3.6칸810인터넷 예제에 흔한 값
0.08178.5 × 0.08 ≈ 14.3칸45아주 거칠게 어림한다

짧은 예시

Python
import cv2

img = cv2.imread("ch13_shapes.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 60, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 넓이가 2,704 인 윤곽선이 파란 네모다
square = max(contours, key=cv2.contourArea)
peri = cv2.arcLength(square, True)         # True: 닫힌 선(처음과 끝이 이어짐)
print(round(peri, 1))                      # 결과: 208.0

# approxPolyDP(윤곽선, epsilon, 닫힌 선인가)
approx = cv2.approxPolyDP(square,          # curve: 어림할 윤곽선
                          0.01 * peri,     # epsilon: 둘레의 1% 까지 비뚤어져도 곧은 선으로
                          True)            # closed: 닫힌 다각형으로
print(len(approx))                         # 결과: 4 → 꼭짓점 4개
print(approx.reshape(-1, 2).tolist())      # 꼭짓점 네 개의 (x, y)

approx 는 (꼭짓점 수, 1, 2) 모양이라 reshape(-1, 2) 로 (꼭짓점 수, 2) 로 폈습니다. 네모의 꼭짓점은 (174, 34), (174, 86), (226, 86), (226, 34) 네 개입니다.

주의할 점

  • 원은 꼭짓점 수가 epsilon 에 따라 크게 바뀝니다. 비율 0.02 에서 원이 꼭짓점 8개가 되어 팔각형과 똑같아집니다. 이 장의 실습은 둘을 가르려고 0.01 을 씁니다.
  • cv2.CHAIN_APPROX_SIMPLE 로 찾은 윤곽선도 곧은 변의 가운데 점을 이미 줄여 둔 것입니다. 그래도 둥근 곳의 점은 많이 남아 있어서 approxPolyDP 가 필요합니다.
← 이전 절13장 · 모양으로 가려내기다음 절 →13장 · 원형도