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

13장. Shape 분석과 ROI 처리

종횡비와 채움 비율

택배 상자에 물건을 담는다고 해 봅시다. 우산은 길쭉한 상자가 필요하고, 공은 정육면체 상자가 맞습니다. 그리고 공을 상자에 넣으면 네 귀퉁이가 비고, 책을 넣으면 상자가 꽉 찹니다. 상자의 가로세로 비율이 종횡비이고, 상자를 얼마나 채웠는지가 채움 비율입니다.

긴 막대, 네모, 원, 기운 네모를 감싼 네모 상자와 종횡비, 채움 비율을 적은 그림

그림의 보라 네모가 12장에서 본 바운딩 박스(cv2.boundingRect)입니다. 긴 막대는 상자가 가로로 길어 종횡비가 3 쯤이고, 네모와 원은 1 입니다. 채움 비율은 네모와 막대가 1 에 가깝고, 원은 귀퉁이가 비어 0.73 쯤입니다. 오른쪽 기운 네모는 상자가 커져 채움 비율이 0.6 쯤으로 떨어집니다. 다홍 네모는 12장의 회전 상자(cv2.minAreaRect)이고, 이 상자로 재면 기운 네모도 꽉 찹니다. 여기서 택배 상자가 감싸는 상자, 빈 귀퉁이가 채움 비율을 깎는 몫입니다.

두 숫자 구하기

숫자식긴 막대(65×21, 넓이 1,280)네모(53×53, 넓이 2,704)
종횡비가로 ÷ 세로65 ÷ 21 ≈ 3.1053 ÷ 53 = 1.00
채움 비율넓이 ÷ (가로 × 세로)1,280 ÷ 1,365 ≈ 0.942,704 ÷ 2,809 ≈ 0.96

boundingRect 의 가로세로는 끝 칸까지 세어서 그린 크기보다 1칸 큽니다. 넓이(contourArea)는 테두리 점을 이은 다각형의 넓이라 반 칸쯤 작게 재어집니다. 그래서 꽉 찬 네모도 채움 비율이 1 이 아니라 0.96 쯤 나옵니다.

짧은 예시

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)

for c in contours:
    x, y, w, h = cv2.boundingRect(c)
    # 가운데가 오른쪽 위(x 250 넘음, y 100 아래)인 것이 긴 막대다
    if x > 240 and y < 100:
        aspect = w / h                          # 종횡비
        extent = cv2.contourArea(c) / (w * h)   # 채움 비율
        print(w, h, round(aspect, 2), round(extent, 3))   # 결과: 65 21 3.1 0.938

주의할 점

  • boundingRect 는 언제나 똑바로 선 상자입니다. 물체가 기울면 상자가 커져 채움 비율이 떨어지고, 기운 막대는 종횡비도 1 에 가까워집니다. 기운 물체는 cv2.minAreaRect 의 가로세로로 잽니다.
  • 종횡비는 가로 ÷ 세로라서, 세로로 선 막대는 0.3 처럼 1 보다 작게 나옵니다. 방향과 관계없이 "얼마나 길쭉한가"만 보려면 긴 변 ÷ 짧은 변으로 잽니다.
← 이전 절13장 · 원형도다음 절 →13장 · 볼록 껍질과 볼록 비율