中央値を用いて縮小するにはどの様にしたらいいでしょうか?
6x6 を 2x2 のするには、6x6 の配列を 3x3 の4つのブロックに分けて、各ブロックでのメディアンを計算することに該当します。
OpenCV に median フィルタがありますが、カーネルサイズやストライドは指定できなかったので、以下のように numpy で作ってみました。
- numpy の as_strided で 6x6 の配列を 3x3 の4つのブロックに分ける。
as_strided の部分は numpy が内部でどのようにデータを管理しているかを知っていないと理解するのが難しいかもしれません。
NumPyのstride_tricks.as_stridedの使用例 - Qiita
- numpy.median() で各ブロックごとに中央値を計算する。
サンプルコード
python
1import numpy as np
2from numpy.lib.stride_tricks import as_strided
3
4a = np.array(
5 [
6 [1, 1, 1, 2, 2, 2],
7 [3, 3, 3, 4, 4, 4],
8 [5, 5, 5, 6, 6, 6],
9 [1, 1, 1, 3, 3, 3],
10 [5, 5, 5, 2, 2, 2],
11 [6, 6, 6, 4, 4, 4],
12 ]
13)
14
15
16def resize(img, size):
17 dst_w, dst_h = size # リサイズ後の画像の大きさ
18 img_h, img_w = img.shape # 画像の大きさ
19 kernel_w, kernel_h = img_w // dst_w, img_h // dst_h # カーネルの大きさ
20
21 # 形状とストライド
22 shape = img_h // kernel_h, img_w // kernel_w, kernel_h, kernel_w
23 strides = img.itemsize * np.array([img_w * kernel_h, kernel_w, img_w, 1])
24 blocks = as_strided(img, shape=shape, strides=strides)
25 # print(blocks)
26
27 # 各ブロックごとに中央値を計算する。
28 median = np.median(blocks, axis=(2, 3)).astype(int)
29
30 return median
31
32
33dst = resize(a, (2, 2))
34print(dst)
35# [[3 4]
36# [5 3]]
代替案
また,中央値以外での縮小方法もあれば教えていただきたいです.
cv2.resize() の interpolation 引数で指定できる方法ではだめなのでしょうか?
- cv2.INTER_NEAREST: 最近傍補間
- cv2.INTER_LINEAR: バイリニア補間 (デフォルト)
- cv2.INTER_CUBIC: バイキュービック補間
- cv2.INTER_AREA: ピクセル領域の関係を利用したリサンプリング
- cv2.INTER_LANCZOS4: Lanczos 補間