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

6장. 평균 필터와 Gaussian 필터

Gaussian 필터

여럿이 함께 쓰는 단체 사진을 고를 때를 떠올려 봅시다. 가운데 선 사람의 의견을 가장 크게 듣고, 가장자리 사람의 의견은 조금만 듣습니다. 평균 필터는 이웃 아홉 칸의 의견을 똑같이 1/9 씩 들었습니다. Gaussian 필터는 가운데 칸의 의견을 가장 크게, 먼 칸일수록 작게 듣는 가중 평균입니다. 무게를 그래프로 그리면 종 모양이 됩니다.

평균 필터의 고른 무게와 Gaussian 필터의 종 모양 무게, 시그마에 따라 달라지는 무게를 견준 막대그래프

왼쪽은 크기 5 의 평균 필터 무게로, 다섯 칸이 모두 0.2 입니다. 가운데는 같은 크기의 Gaussian 무게로, 가운데 칸이 0.375 로 가장 크고 양 끝은 0.062 입니다. 오른쪽은 크기 9 에서 시그마를 1, 2, 4 로 바꾼 무게입니다. 시그마가 클수록 종이 납작하게 퍼져 평균 필터에 가까워집니다. 여기서 가운데 선 사람이 가운데 칸이고, 의견을 듣는 비율이 커널의 무게입니다.

평균 필터는 모든 칸에 같은 무게를, Gaussian 필터는 가운데에 큰 무게를 준다는 비교 그림

두 상자는 무게를 나누는 두 방식을 견줍니다. 가까운 칸일수록 원래 칸과 닮았을 가능성이 크므로, 가운데에 무게를 몰아주면 경계가 덜 번집니다.

파스칼 삼각형으로 무게 만들기

Gaussian 무게는 파스칼 삼각형의 숫자로 손쉽게 흉내 낼 수 있습니다. 위의 두 수를 더해 아래 수를 만듭니다.

줄숫자합쓰임
11 12
21 2 14크기 3 의 무게 (1/4, 2/4, 1/4)
31 3 3 18
41 4 6 4 116크기 5 의 무게 (1/16, 4/16, 6/16, 4/16, 1/16)

가로 무게 1-2-1 과 세로 무게 1-2-1 을 곱하면 3×3 무게가 됩니다. 가운데는 2×2 = 4, 모서리는 1×1 = 1 입니다.

121
1121
2242
1121

아홉 무게의 합은 16 입니다. 앞의 손계산 이웃(가운데 145)에 이 무게를 곱해 더하면 다음과 같습니다.

단계계산
① 무게를 곱해 더하기1×98 + 2×103 + 1×101 + 2×97 + 4×145 + 2×99 + 1×102 + 2×100 + 1×96 = 1775
② 무게의 합으로 나누기1775 ÷ 16 = 110.94
③ 정수로 반올림111

평균 필터는 105 였는데 Gaussian 은 111 입니다. 가운데 칸(145)의 무게가 4/16 으로 커서, 같은 크기에서는 튄 값을 덜 누그러뜨립니다. 그 대신 경계도 덜 뭉갭니다. 이 저울질은 다음 절에서 견줍니다.

cv2.GaussianBlur 의 인자

인자예뜻
srcimg필터를 걸 그림
ksize(5, 5)커널 크기. 반드시 홀수
sigmaX0 또는 1.5가로 방향 시그마(퍼짐 정도). 0 이면 커널 크기에 맞춰 스스로 정한다(크기 3 이면 0.8, 5 면 1.1, 9 면 1.7)
sigmaY주지 않음세로 방향 시그마. 주지 않으면 sigmaX 와 같다

크기를 (0, 0) 으로 주고 시그마만 주면 시그마에 맞춰 크기를 스스로 정합니다. 둘 중 하나는 꼭 정해 줘야 합니다.

짧은 예시

Python
import cv2

# getGaussianKernel(크기, 시그마): 한 줄짜리 Gaussian 무게를 돌려준다. 모양은 (크기, 1)
g = cv2.getGaussianKernel(5, 0)
print([round(float(v), 4) for v in g.ravel()])    # 결과: [0.0625, 0.25, 0.375, 0.25, 0.0625]
print([round(float(v) * 16) for v in g.ravel()])  # 결과: [1, 4, 6, 4, 1] → 파스칼 삼각형 넷째 줄

# 가로 무게와 세로 무게를 곱하면(@) 3×3 무게가 된다. 16 을 곱하면 정수로 보인다
g3 = cv2.getGaussianKernel(3, 0)
print((g3 @ g3.T * 16).astype(int).tolist())      # 결과: [[1, 2, 1], [2, 4, 2], [1, 2, 1]]

@ 는 세로 한 줄(3×1)과 가로 한 줄(1×3)을 곱해 3×3 표를 만드는 기호입니다. g3.T 의 T 는 transpose(뒤집어 눕히기)를 줄인 말로, 세로 줄을 가로 줄로 눕힙니다.

주의할 점

  • cv2.GaussianBlur 의 ksize 에 짝수를 주면 오류가 납니다. 3, 5, 7, 9 처럼 홀수만 씁니다.
  • 시그마를 크게 주고 커널 크기를 작게 주면, 종이 커널 밖으로 잘려 평균 필터와 비슷해집니다. 시그마를 키우면 크기도 함께 키우거나, 크기를 (0, 0) 으로 맡깁니다.
← 이전 절6장 · 가장자리 처리다음 절 →6장 · 평균 필터와 Gaussian 필터 견주기