13장. Shape 분석과 ROI 처리
ROI 란
신문을 펼치면 기사, 광고, 사진이 한 면에 빽빽합니다. 관심 있는 기사 하나만 읽고 싶으면 가위로 그 기사만 오려 냅니다. 오린 조각은 작아서 들고 다니기 쉽고, 다른 기사에 눈이 가지 않습니다. 사진에서 필요한 부분만 골라 다루는 관심 영역(ROI)이 이 오려 낸 기사입니다.
그림의 세 상자가 ROI 를 쓰는 까닭입니다. 칸 수가 줄어 계산이 빨라지고, 다른 물체가 끼어들지 않아 결과가 정확해지고, 필요한 곳에만 처리를 걸 수 있습니다. 여기서 신문 한 면이 전체 사진, 오려 낸 기사가 ROI 입니다.
왼쪽은 책상 위 택배 상자 사진 전체(320×240 = 76,800칸)이고, 보라 네모가 송장의 자리입니다. 오른쪽은 그 네모만 잘라 낸 ROI(145×113 = 16,385칸)입니다. 송장 글자를 읽거나 바코드를 찾을 때 오른쪽만 다루면 칸 수가 5분의 1 쯤으로 줄고, 상자의 테이프나 스티커가 끼어들지 않습니다. 송장의 이름, 주소, 전화번호는 지어낸 것입니다.
ROI 의 모양과 만드는 법
| ROI 모양 | 만드는 법 | 결과 | 이 장의 절 |
|---|---|---|---|
| 네모 | 슬라이싱 img[y:y+h, x:x+w] | 작은 그림 한 장 | 사각형 ROI |
| 동그라미, 다각형 | 마스크 + cv2.bitwise_and | 원본 크기, ROI 밖은 검정 | 모양 ROI |
| 사람이 고른 네모 | cv2.selectROI | (x, y, 가로, 세로) | ROI 안에서만 처리하기 |
ROI 를 쓰는 곳
| 장면 | 관심 영역 | 앞 장과 이어짐 |
|---|---|---|
| 송장 읽기 | 흰 송장 네모 | 8장의 이진화를 송장에만 |
| 작은 부품 검사 | 부품 둘레의 네모 | 8장: 물체가 아주 작으면 잘라서 Otsu |
| 색으로 물건 고르기 | 고른 물체의 상자 | 3장의 HSV 마스크 |
| 얼굴·번호판 가리기 | 가릴 곳만 | 6장의 블러를 그곳에만 |
짧은 예시
import cv2
img = cv2.imread("ch13_parcel.png")
# 송장의 자리: 가로 60~204, 세로 40~152 → [세로 범위, 가로 범위] 로 자른다
label = img[40:153, 60:205]
print(img.shape, "→", label.shape) # 결과: (240, 320, 3) → (113, 145, 3)
# 칸 수가 얼마나 줄었나
whole = img.shape[0] * img.shape[1]
part = label.shape[0] * label.shape[1]
print(whole, part, round(part / whole, 3)) # 결과: 76800 16385 0.213주의할 점
- ROI 를 너무 딱 맞게 자르면 물체의 가장자리가 잘립니다. 몇 칸의 여백을 붙여 자르는 것이 안전합니다(다음 절).
- ROI 의 좌표는 ROI 안에서 다시 (0, 0) 부터 셉니다. ROI 안에서 찾은 자리를 원본에 표시하려면 ROI 의 왼쪽 위 (x, y) 를 더해야 합니다.