7장. Median 과 Bilateral 필터, 필터 비교
중앙값이란
운동회 날 아홉 명을 키 순서로 한 줄로 세웠다고 해 봅시다. 맨 앞에는 가장 작은 학생, 맨 뒤에는 가장 큰 학생이 섭니다. 줄의 한가운데, 다섯째 자리에 선 학생의 키가 중앙값입니다. 키가 유난히 큰 학생이 한 명 끼어 있어도 그 학생은 맨 뒤로 갈 뿐, 다섯째 자리의 학생은 바뀌지 않습니다.
그림의 네 걸음이 Median 필터가 칸 하나를 고치는 순서입니다. 아홉 칸을 모아 작은 값부터 줄 세우고, 다섯째 값을 골라 새 그림의 같은 자리에 써 넣습니다. 여기서 키 순서로 선 줄이 줄 세운 아홉 칸이고, 다섯째 학생이 중앙값입니다. 하얀 점(255)은 늘 줄의 맨 뒤로, 검은 점(0)은 맨 앞으로 밀려나므로 가운데에 뽑히기 어렵습니다.
손계산: 줄 세워 가운데 값 고르기
| 단계 | 하얀 점이 섞인 아홉 칸 | 하얀 점 셋이 섞인 아홉 칸 |
|---|---|---|
| 아홉 칸 | 90, 92, 93, 95, 255, 91, 94, 96, 93 | 90, 255, 93, 95, 255, 91, 255, 96, 93 |
| 줄 세우기 | 90, 91, 92, 93, 93, 94, 95, 96, 255 | 90, 91, 93, 93, 95, 96, 255, 255, 255 |
| 다섯째 값(중앙값) | 93 | 95 |
| 평균과 견주면 | 평균 111 | 평균 147 |
점이 셋이어도 중앙값은 95 로 이웃과 비슷하게 남습니다. 아홉 칸 가운데 점이 다섯 개 이상이 되면 그때는 중앙값도 점의 값이 됩니다. 커널 안 칸의 절반 넘게 점이면 Median 필터도 버티지 못한다는 뜻입니다.
짧은 예시
import numpy as np
nine = np.array([90, 92, 93, 95, 255, 91, 94, 96, 93])
# sort: 작은 값부터 줄 세운다. 아홉 개이므로 다섯째(번호 4)가 한가운데다
print(np.sort(nine)) # 결과: [ 90 91 92 93 93 94 95 96 255]
print(int(np.sort(nine)[4])) # 결과: 93
# np.median: 같은 일을 한 번에 한다
print(float(np.median(nine)), float(nine.mean())) # 결과: 93.0 111.0주의할 점
- 값의 개수가 짝수면 한가운데가 둘이라,
np.median은 두 값의 평균을 돌려줍니다. Median 필터는 커널이 늘 홀수 × 홀수라 이런 일이 없습니다. - 중앙값은 커널 안에 실제로 있던 값 가운데 하나를 고르므로, 평균처럼 없던 새 밝기(117 같은)를 만들지 않습니다.