質問画像の処理は画像処理でそれぞれ平均フィルタ、メディアンフィルタと呼ばれるものです。
scipy などのライブラリにある実装を使うか、numpy で自分で実装してもよいです。
scipy を使う場合
どちらも scipy に関数があります。
平均フィルタは scipy.ndimage.convolve() で各要素が 1 / 9
であるカーネルでフィルタリングすると、計算できます。
メディアンフィルタは scipy.ndimage.median_filter() を使うと計算できます。
python
1from scipy import ndimage
2
3# 平均フィルタ
4kernel = np.full((3, 3), 1 / 9)
5mean = ndimage.convolve(a, kernel)[1:-1, 1:-1] # [1:-1, 1:-1] は padding 分を削っている
6print(mean)
7
8# メディアンフィルタ
9median = ndimage.median_filter(a, size=3)[1:-1, 1:-1]
10print(mean)
numpy を使った実装例
python
1a = np.array(
2 [
3 [10, 15, 12, 6, 4],
4 [10, 12, 11, 6, 6],
5 [15, 14, 14, 3, 1],
6 [3, 5, 2, 3, 5],
7 [3, 2, 3, 5, 2],
8 ]
9)
10filter_size = (3, 3)
11
12# フィルタリング後の出力サイズはパディングなしの場合
13# (高さ - フィルタの高さ + 1, 幅 - フィルタの幅 + 1)
14out_h = a.shape[0] - filter_size[0] + 1
15out_w = a.shape[1] - filter_size[1] + 1
16
17output = np.empty((out_h, out_w), dtype=a.dtype)
18
19for i in range(a.shape[0] - 2):
20 for j in range(a.shape[1] - 2):
21 window = np.array(a[i : i + 3, j : j + 3])
22 print(f"i = {i}, j = {j}\n", window)
23 output[i, j] = window.mean()
24
25print(output)
numpy の実装例を stride trick を使って書いた例
python
1import numpy as np
2
3a = np.array(
4 [
5 [10, 15, 12, 6, 4],
6 [10, 12, 11, 6, 6],
7 [15, 14, 14, 3, 1],
8 [3, 5, 2, 3, 5],
9 [3, 2, 3, 5, 2],
10 ]
11)
12
13# フィルタをスライドさせたときに重なる各領域を表す配列を stride trick で作る
14filter_size = (3, 3)
15# フィルタリング後の出力サイズはパディングなしの場合
16# (高さ - フィルタの高さ + 1, 幅 - フィルタの幅 + 1) なので
17output_size = tuple(np.subtract(a.shape, filter_size) + 1)
18
19shape = output_size + filter_size
20strides = a.strides + a.strides
21view = np.lib.stride_tricks.as_strided(a, shape, strides)
22print(view)
23
24# メディアンフィルタ
25mean = np.median(view, axis=(2, 3))
26print("メディアンフィルタ", mean.astype(int))
27
28# 平均フィルタ
29median = np.mean(view, axis=(2, 3))
30print("平均フィルタ", median.astype(int))
メディアンフィルタ
[[12 12 6]
[11 6 5]
[ 3 3 3]]
平均フィルタ
[[12 10 7]
[ 9 7 5]
[ 6 5 4]]