Hello Wor.log

IT系大学生4人による備忘録のようなもの

numpyで配列を格子状に分割する

CPPXのXです。

画像とかを格子状に分割したかったのですが、どうも関数一発でできないみたいなのでまとめておきます。
そういう関数があったら教えてください。

np.splitで軸を複数指定できればよかったのになあという感じです。

どうにも一発でできないみたいなので、縦分割して...次横分割して...みたいなことをします。

では目次です。

環境

imports

import numpy as np

前準備

使うデータを用意します。

t = np.array([
    [1, 2, 3, 4, 5, 6],
    [1, 2, 3, 4, 5, 6],
    [9, 8, 7, 6, 5, 4],
    [9, 8, 7, 6, 5, 4],
    [1, 2, 3, 4, 5, 6],
    [1, 2, 3, 4, 5, 6],
    ]) #[..., np.newaxis] # 6x6x1

6x6のデータです。
6x6x3とか、次元を増やしても大丈夫です。

れっつ分割

分割後の格子数が3x3になるように分割してみます。

np.concatenate(np.hsplit(np.stack(np.hsplit(t, 3)), 3))

これで分割できます(shape: 9x2x2)。
6x2x3にしたい場合は、

np.concatenate(np.hsplit(np.stack(np.hsplit(t, 2)), 3))

こうします。
こんな感じに分割されます。

1 2 3 | 4 5 6
1 2 3 | 4 5 6
------------
9 8 7 | 6 5 4
9 8 7 | 6 5 4
------------
1 2 3 | 4 5 6
1 2 3 | 4 5 6
np.concatenate(np.hsplit(np.stack(np.hsplit(t, 横方向の格子の数)), 縦方向の格子の数))

こうですね。

6x6x3のデータを3x3に分割したら、9x2x2x3になります。

詳細

最初に縦分割します。

np.hsplit(t, 3)

戻り値がリストなので、stackで積み上げます。

np.stack(np.hsplit(t, 3))

この状態で、shapeを見ると3x6x2になります。
縦方向に分割されたものが、横向きに重なっているような状態になっているので、もう一度hsplitで縦分割します。

np.hsplit(np.stack(np.hsplit(t, 3)), 3)

リストが返ってくるので、最初と同様積み上げるのですが、最初に切ったものと区別する必要がないのでconcatenateで連結します。

np.concatenate(np.hsplit(np.stack(np.hsplit(t, 3)), 3))

この状態でshapeを見ると、9x2x2になっていると思います。
分割完了です。

おわり

切ったりくっつけたりしているので、重いような気がします。

速度は確認していません。