OpenCV 비전 실무12장 · Contour Detection 과 객체 분석10 / 21← 이전목차다음 →MetaContents

12장. Contour Detection 과 객체 분석

물체를 감싸는 상자와 원

택배 상자에 물건을 넣는 일을 떠올려 봅시다. 바닥과 나란한 상자를 고르면 비스듬히 놓인 긴 물건은 상자가 커집니다. 물건 방향으로 상자를 돌려 담으면 훨씬 작은 상자로 됩니다. 둥근 통에 담으려면 물건의 가장 먼 두 끝이 들어가는 원을 고릅니다. 물체를 감싸는 틀도 이렇게 세 가지를 씁니다.

곧은 상자, 회전 상자, 최소 외접원 세 가지 틀을 나란히 놓은 비교 그림

초록 상자의 곧은 상자(cv2.boundingRect)는 변이 화면의 가로세로와 나란합니다. 다홍 상자의 회전 상자(cv2.minAreaRect)는 넓이가 가장 작아지게 물체를 따라 기웁니다. 보라 상자의 최소 외접원(cv2.minEnclosingCircle)은 모든 점을 품는 가장 작은 원입니다. 여기서 바닥과 나란한 택배 상자가 곧은 상자, 돌려 담은 상자가 회전 상자, 둥근 통이 외접원입니다.

도형 판의 도형마다 곧은 상자, 회전 상자, 최소 외접원을 그린 세 그림을 나란히 놓은 그림

같은 도형에 세 가지 틀을 그렸습니다. 왼쪽의 곧은 상자(초록)는 30도 기운 네모와 타원에서 빈자리가 크게 남습니다. 가운데 회전 상자(다홍)는 기운 네모에 꼭 맞습니다. 오른쪽 외접원(보라)은 원에는 꼭 맞지만 길쭉한 도형에서는 빈자리가 많습니다.

세 가지 틀 견주기

틀함수돌려주는 값그리는 법쓰는 곳
곧은 상자cv2.boundingRect(c)(x, y, w, h) 정수 넷cv2.rectangle물체 잘라 내기, 탐지 결과 표시
회전 상자cv2.minAreaRect(c)((중심 x, y), (가로, 세로), 각도)cv2.boxPoints 로 꼭짓점을 구해 cv2.drawContours기운 물체의 길이와 폭
최소 외접원cv2.minEnclosingCircle(c)((중심 x, y), 반지름)cv2.circle둥근 물체의 지름

기운 네모로 견줘 보기

도형 판의 기운 네모는 가로 76, 세로 34 를 30도 돌려 칠했습니다. 교안 PC 에서 잰 값입니다.

잰 것값넓이
contourArea윤곽선이 감싼 넓이2,596
회전 상자76.4 × 35.3약 2,696
곧은 상자83 × 695,727

회전 상자는 칠한 크기(76×34)와 거의 같습니다. 곧은 상자는 물체 넓이의 두 배가 넘습니다. 기운 물체의 길이를 재려면 회전 상자를 씁니다.

짧은 예시

Python
import cv2
import numpy as np

shapes = cv2.imread("ch12_shapes.png", cv2.IMREAD_GRAYSCALE)
contours, _ = cv2.findContours(shapes, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
tilted = contours[5]                                 # 30도 기운 네모

# boundingRect: 왼쪽 위 x, y 와 가로 w, 세로 h
x, y, w, h = cv2.boundingRect(tilted)
print("곧은 상자:", (x, y, w, h))
# minAreaRect: ((중심 x, 중심 y), (가로, 세로), 각도)
(cx, cy), (rw, rh), angle = cv2.minAreaRect(tilted)
print("회전 상자 크기:", round(rw, 1), round(rh, 1))
# boxPoints: 회전 상자의 꼭짓점 네 개(실수). 그리려면 정수(int32)로 바꾼다
box = np.round(cv2.boxPoints(((cx, cy), (rw, rh), angle))).astype(np.int32)
print("꼭짓점:", box.tolist())
# minEnclosingCircle: (중심 x, 중심 y), 반지름
(ox, oy), r = cv2.minEnclosingCircle(contours[6])  # 원
print("원의 외접원 반지름:", round(r, 1))

교안 PC 에서는 곧은 상자가 (221, 24, 83, 69), 회전 상자 크기가 35.3, 76.4, 원의 외접원 반지름이 35.0 입니다. 원은 반지름 35 로 칠했으므로 외접원이 원 자체와 같습니다. 꼭짓점 네 개는 기운 네모의 네 모서리 근처에 놓입니다.

주의할 점

  • cv2.boxPoints 는 실수를 돌려줍니다. OpenCV 5.0 의 cv2.drawContours 는 정수 좌표만 받으므로 np.round(...).astype(np.int32) 로 바꿉니다.
  • 회전 상자의 가로·세로와 각도는 OpenCV 가 정한 기준을 따라서, 같은 상자가 (35.3, 76.4) 로도 (76.4, 35.3) 으로도 나올 수 있습니다. 길이와 폭은 두 값 가운데 큰 쪽과 작은 쪽으로 읽고, 각도는 그림을 그려 확인합니다.
  • cv2.boundingRect 의 w, h 는 칸 수입니다. cv2.rectangle 로 딱 맞게 그리려면 오른쪽 아래를 (x + w - 1, y + h - 1) 로 줍니다.
← 이전 절12장 · 무게중심과 모멘트다음 절 →12장 · 개수 세기와 잡티 걸러 내기