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

13장. Shape 분석과 ROI 처리

모양으로 가려내기

분리수거장의 플라스틱 통에 페트병과 플라스틱 컵이 섞여 있다고 해 봅시다. 둘 다 투명하고 크기도 비슷합니다. 그래도 사람은 금방 가려냅니다. 병은 길쭉하고 목이 좁고, 컵은 위가 넓게 벌어졌기 때문입니다. 색과 크기가 같아도 생김새가 다르면 가려낼 수 있습니다. 컴퓨터에게는 이 "생김새"를 숫자로 바꿔 줘야 합니다.

크기로 가려내기, 색으로 가려내기, 모양으로 가려내기의 세 가지를 견준 비교 그림

그림의 세 상자는 물체를 가려내는 세 가지 단서입니다. 크기는 넓이 하나로, 색은 3장의 HSV 로 가려낼 수 있습니다. 그런데 크기와 색이 같으면 앞의 두 단서는 쓸모가 없고, 셋째 상자의 모양 숫자가 필요합니다. 여기서 페트병과 컵이 크기와 색이 같은 두 물체이고, "길쭉하다, 위가 넓다"가 모양 특징입니다.

도형 판 그림에 여덟 도형의 이름을 적은 그림. 같은 색끼리 모양이 다르다

이 장의 실습에 쓰는 도형 판입니다. 원과 팔각형은 같은 빨강, 세모와 별은 같은 노랑, 네모와 기운 네모는 같은 파랑, 긴 막대와 초승달은 같은 초록입니다. 색으로는 짝을 가를 수 없고, 넓이도 원(2,212칸)과 기운 네모(2,074칸)처럼 비슷한 것이 많습니다. 이 장에서는 이 여덟 개를 모양 숫자만으로 가려냅니다.

12차시에서 본 윤곽선 함수 되짚기

모양 숫자는 모두 윤곽선에서 시작합니다. 12장에서 본 함수를 한 줄씩만 되짚습니다.

함수돌려주는 것이 장에서 쓰는 곳
cv2.findContours(이진, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)바깥 윤곽선 목록모든 실습의 시작
cv2.contourArea(c)면적(칸 수에 가까운 값)원형도, 채움 비율, 볼록 비율
cv2.arcLength(c, True)둘레 길이원형도, epsilon
cv2.drawContours(그림, [c], -1, 색, 두께)윤곽선 그리기(두께 -1 은 속까지 채우기)이름 그림, 모양 ROI 마스크
cv2.boundingRect(c)바운딩 박스 (x, y, 가로, 세로)종횡비, 채움 비율, 사각형 ROI
cv2.minAreaRect(c)회전 상자(기울어진 채로 감싸는 가장 작은 네모)기운 물체의 종횡비

모양 특징 한눈에 보기

특징구하는 법원네모긴 막대별
꼭짓점 수approxPolyDP많다4410
원형도4π×넓이 ÷ 둘레²1 에 가깝다약 0.785작다아주 작다
종횡비가로 ÷ 세로11크다(3 쯤)1 쯤
채움 비율넓이 ÷ 상자 넓이약 0.78511 에 가깝다작다
볼록 비율넓이 ÷ 볼록 껍질 넓이111작다

짧은 예시

Python
import cv2

# 도형 판을 읽고 흑백으로 바꾼 뒤, 바탕(밝기 40)보다 밝은 곳을 흰색으로
img = cv2.imread("ch13_shapes.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 60, 255, cv2.THRESH_BINARY)

# 12차시에서 본 대로 바깥 윤곽선만 찾는다
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))   # 결과: 8 → 도형 여덟 개

# 넓이만으로는 원과 기운 네모가 잘 갈리지 않는다
areas = sorted(int(cv2.contourArea(c)) for c in contours)
print(areas)           # 결과: [1230, 1272, 1280, 1344, 2074, 2212, 2558, 2704]

넓이를 작은 것부터 늘어놓으면 1,230 부터 1,344 까지 네 개가 몰려 있고, 2,074 부터 2,704 까지 네 개가 몰려 있습니다. 넓이로는 "작은 무리, 큰 무리" 정도만 나뉩니다.

주의할 점

  • 모양 숫자는 윤곽선이 잘 찾아졌을 때만 믿을 수 있습니다. 이진화가 잘못돼 물체 둘이 붙거나 하나가 쪼개지면 숫자도 엉뚱하게 나옵니다. 8장의 이진화와 9장의 모폴로지로 먼저 깨끗한 마스크를 만듭니다.
  • 12장에서는 밝은 바탕의 어두운 부품을 cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU 로 이진화했습니다. 이 장의 도형 판은 거꾸로 바탕이 어둡고(밝기 40) 도형이 밝으므로(105 이상) 뒤집지 않는 cv2.THRESH_BINARY 를 쓰고, 기준값도 그 사이의 60 으로 정했습니다. 실제 사진은 바탕이 고르지 않을 수 있습니다. 잡티가 없는 그림이라 12장의 "면적 100 이상만 남기기"도 생략했습니다.
← 이전 절13장 · 용어 짚고 가기다음 절 →13장 · 근사 다각형