画像処理ではよく使われるメディアンフィルター。
OpenCVを使えば画像の2次元配列に対して
median = cv2.medianBlur(img,5)
とするだけで処理できる。
時系列データなどの1次元データにおいても外れ値がある場合,
メディアンフィルターで取り除くことができる。
1次元用のメディアンフィルターというのはnumpyにもopencvにも関数が見当たらず,
すこし工夫したのでメモ。
インデックスで各点ごとに中央値を選ぶ領域を抽出して2次元配列にしてから,
np.medianを行方向に適用している。
median.py
import numpy as np
import matplotlib.pyplot as plt
# 1次元配列に対するメディアンフィルター
# kはフィルターの大きさで奇数
def median1d(arr, k):
w = len(arr)
idx = np.fromfunction(lambda i, j: i + j, (k, w), dtype=np.int) - k // 2
idx[idx < 0] = 0
idx[idx > w - 1] = w - 1
return np.median(arr[idx], axis=0)
# 外れ値を含む正弦波
x = np.sin(np.arange(1000) / 50)
x[np.random.randint(0, len(x), 20)] += np.random.randn(20) * 3
# フィルタリング
y = median1d(x, 5)
plt.figure(1)
plt.clf()
plt.subplot(2, 1, 1)
plt.plot(x)
plt.ylim([-3, 3])
plt.subplot(2, 1, 2)
plt.plot(y)
plt.ylim([-3, 3])