6장. 평균 필터와 Gaussian 필터
가장자리 처리
교실 맨 앞줄 끝자리에 앉은 학생은 앞과 옆에 친구가 없습니다. 모둠 평균을 내려는데 사람 수가 모자랍니다. 이럴 때 빈자리를 0 점으로 채울지, 옆 친구 점수를 한 번 더 쓸지 정해야 합니다. 사진의 맨 가장자리 칸도 바깥에 이웃이 없습니다. OpenCV 는 바깥에 칸을 덧대어(패딩) 채운 뒤 계산하고, 채우는 방법을 borderType 으로 고릅니다.
그림의 네 상자가 바깥 칸을 채우는 네 방법입니다. 줄 10 20 30 40 의 왼쪽 바깥 두 칸을 무엇으로 채우는지 견주어 보세요. 여기서 빈자리가 사진 바깥 칸이고, 빈자리를 채우는 규칙이 borderType 입니다.
네 가지 채우는 법
| 이름 | 왼쪽 바깥 두 칸 | 원래 줄 | 오른쪽 바깥 두 칸 | 뜻 |
|---|---|---|
cv2.BORDER_CONSTANT | 0 0 | 10 20 30 40 | 0 0 | 정한 값(기본 0)으로 채운다. constant 는 "변하지 않는 값" |
cv2.BORDER_REPLICATE | 10 10 | 10 20 30 40 | 40 40 | 끝값을 그대로 복사한다. replicate 는 "복제하다" |
cv2.BORDER_REFLECT | 20 10 | 10 20 30 40 | 40 30 | 끝 칸을 포함해 거울에 비춘다. reflect 는 "반사하다" |
cv2.BORDER_REFLECT_101 | 30 20 | 10 20 30 40 | 30 20 | 끝 칸을 빼고 거울에 비춘다. OpenCV 필터의 기본값(BORDER_DEFAULT) |
짧은 예시
import cv2
import numpy as np
row = np.array([[10, 20, 30, 40]], dtype=np.uint8)
# copyMakeBorder(그림, 위, 아래, 왼쪽, 오른쪽, 채우는 법): 바깥에 칸을 덧댄다
print(cv2.copyMakeBorder(row, 0, 0, 2, 2, cv2.BORDER_REFLECT_101).ravel())
# 결과: [30 20 10 20 30 40 30 20]
# 필터에도 borderType 으로 준다. 가로 3칸, 세로 1칸 평균
print(cv2.blur(row, (3, 1)).ravel()) # 결과: [17 20 30 33]
print(cv2.blur(row, (3, 1), borderType=cv2.BORDER_CONSTANT).ravel()) # 결과: [10 20 30 23]기본값(REFLECT_101)이면 첫 칸은 바깥의 20 을 빌려 (20 + 10 + 20) ÷ 3 = 16.7, 반올림해 17 입니다. 0 으로 채우면 (0 + 10 + 20) ÷ 3 = 10 이 되어 가장자리가 어두워집니다.
주의할 점
BORDER_CONSTANT로 큰 커널을 걸면 사진 둘레에 어두운 테두리가 생깁니다. 특별한 까닭이 없으면 기본값을 그대로 씁니다.- 가장자리의 몇 칸은 어떤 방법을 써도 "지어낸 이웃"으로 계산한 값입니다. 커널이 클수록 그런 칸이 많아집니다.