OpenCV 비전 실무6장 · 평균 필터와 Gaussian 필터5 / 21← 이전목차다음 →MetaContents

6장. 평균 필터와 Gaussian 필터

평균 필터

반 학생 아홉 명의 시험 점수를 한 사람씩 발표하면 한두 명이 유난히 높거나 낮아 들쭉날쭉합니다. 대신 "우리 모둠 평균"을 말하면 숫자가 고르게 다듬어집니다. 평균 필터는 칸마다 자기와 이웃의 평균을 새 값으로 씁니다. 튀는 칸은 이웃과 섞여 누그러지고, 고른 면은 그대로 고르게 남습니다.

cv2.blur, cv2.boxFilter, normalize=False 의 boxFilter 를 나란히 놓은 비교 그림

그림의 세 상자는 OpenCV 에서 평균 필터를 거는 방법입니다. 왼쪽 둘은 같은 결과를 내고, 오른쪽은 평균을 내지 않고 합만 구합니다. 여기서 모둠이 커널 크기만큼의 이웃이고, 모둠 평균이 새 값입니다.

평균 필터를 거는 함수

함수쓰는 법하는 일
cv2.blurcv2.blur(img, (3, 3))3×3 이웃의 평균. 가장 간단하다
cv2.boxFiltercv2.boxFilter(img, -1, (3, 3))cv2.blur 와 같다. 둘째 인자 -1 은 "원본과 같은 자료형으로"
cv2.boxFilter + normalize=Falsecv2.boxFilter(img, cv2.CV_32F, (3, 3), normalize=False)나누지 않고 아홉 칸의 합만. 합은 255 를 넘으므로 소수(CV_32F)로 받는다

normalize 는 "고르게 맞추다"라는 뜻으로, 여기서는 칸 수로 나눠 평균을 낸다는 말입니다. CV_32F 는 32비트 소수(float)라는 뜻입니다. ksize 는 (가로, 세로) 순서로 주며, 이 장에서는 늘 정사각형을 씁니다.

짧은 예시

Python
import cv2
import numpy as np

# 고른 면(100) 가운데에 손계산과 같은 3×3 숫자를 넣은 5×5 그림
a = np.full((5, 5), 100, dtype=np.uint8)
a[1:4, 1:4] = [[98, 103, 101], [97, 145, 99], [102, 100, 96]]

# blur = 흐리게 하다. (3, 3) 은 커널 크기
print(int(cv2.blur(a, (3, 3))[2, 2]))                       # 결과: 105 → 손계산과 같다
print(int(cv2.boxFilter(a, -1, (3, 3))[2, 2]))              # 결과: 105 → blur 와 같다
print(float(cv2.boxFilter(a, cv2.CV_32F, (3, 3), normalize=False)[2, 2]))   # 결과: 941.0 → 합

a[2, 2] 가 손계산의 가운데 칸입니다. 손으로 구한 105 와 OpenCV 가 구한 105 가 같습니다.

주의할 점

  • 평균 필터는 튄 칸을 없애지 않고 이웃에 나눠 퍼뜨립니다. 145 의 튄 몫이 둘레 여덟 칸에도 조금씩 섞여, 둘레의 100 근처 칸들도 104~105 로 오릅니다.
  • 컬러 그림에 걸면 B, G, R 채널마다 따로 평균을 냅니다. 함수는 같습니다.
← 이전 절6장 · 필터와 커널다음 절 →6장 · 커널 크기의 효과