NumPy配列ndarrayをタイル状に繰り返し並べるnp.tile
NumPyの関数np.tile()を使うと配列ndarrayを任意のタイル状に繰り返し並べた新たなndarrayを生成できる。
ここでは以下の内容について説明する。
np.tile()の基本的な使い方- 二次元配列(多次元配列)の場合
- 画像処理への応用(タイル状に繰り返し並べる)
np.tile()の基本的な使い方
一次元配列を例とする。
import numpy as np
a = np.arange(3)
print(a)
# [0 1 2]
np.tile()の第一引数Aに元のndarray、第二引数repsに繰り返す数を指定する。新たな配列が返され、元の配列自体は変更されない。
a_tile = np.tile(a, 3)
print(a_tile)
# [0 1 2 0 1 2 0 1 2]
print(a)
# [0 1 2]
第二引数repsにタプルを指定すると、各軸に対して元の配列が繰り返される。
例えばrepsを(2, 3)とすると、axis=0(行方向)に2回、axis=1(列方向)に3回繰り返され、結果は二次元配列になる。
なお行方向・列方向という言葉は定義が曖昧だが、ここでは行数が増えると伸びていく方向(=縦)を行方向、列数が増えると伸びていく方向(=横)を列方向としている。
print(np.tile(a, (2, 3)))
# [[0 1 2 0 1 2 0 1 2]
# [0 1 2 0 1 2 0 1 2]]
print(np.tile(a, (2, 3)).shape)
# (2, 9)
タプルの要素数が増えた場合も考え方は同じ。タプルの要素数が3だと三次元配列となる。
print(np.tile(a, (2, 3, 4)))
# [[[0 1 2 0 1 2 0 1 2 0 1 2]
# [0 1 2 0 1 2 0 1 2 0 1 2]
# [0 1 2 0 1 2 0 1 2 0 1 2]]
#
# [[0 1 2 0 1 2 0 1 2 0 1 2]
# [0 1 2 0 1 2 0 1 2 0 1 2]
# [0 1 2 0 1 2 0 1 2 0 1 2]]]
print(np.tile(a, (2, 3, 4)).shape)
# (2, 3, 12)
二次元配列(多次元配列)の場合
元の配列ndarrayが多次元配列の場合として二次元配列を例とする。
a_2d = np.arange(6).reshape(2, 3)
print(a_2d)
# [[0 1 2]
# [3 4 5]]
第二引数repsを整数で指定したり、元の配列の次元数ndim(二次元配列の場合は2)より少ない要素数のタプルで指定したりする場合、最後の次元の軸に沿って元の配列が繰り返される。
例えばreps=2やreps=(2, )(要素数1個のタプル)とすると以下のような結果となる。
print(np.tile(a_2d, 2))
# [[0 1 2 0 1 2]
# [3 4 5 3 4 5]]
print(np.tile(a_2d, (2, )))
# [[0 1 2 0 1 2]
# [3 4 5 3 4 5]]
これはreps=(1, 2)と等価。axis=1に対して2回繰り返される。
print(np.tile(a_2d, (1, 2)))
# [[0 1 2 0 1 2]
# [3 4 5 3 4 5]]
axis=0に対してのみ繰り返したい場合は、例えばreps=(2, 1)とすればよい。
print(np.tile(a_2d, (2, 1)))
# [[0 1 2]
# [3 4 5]
# [0 1 2]
# [3 4 5]]
一次元配列の例と同様に、元の配列より次元を増やすことも可能。
print(np.tile(a_2d, (2, 2, 2)))
# [[[0 1 2 0 1 2]
# [3 4 5 3 4 5]
# [0 1 2 0 1 2]
# [3 4 5 3 4 5]]
#
# [[0 1 2 0 1 2]
# [3 4 5 3 4 5]
# [0 1 2 0 1 2]
# [3 4 5 3 4 5]]]
print(np.tile(a_2d, (2, 2, 2)).shape)
# (2, 4, 6)
画像処理への応用(タイル状に繰り返し並べる)
np.tile()を利用するとNumPy配列ndarrayとして読み込んだ画像をタイル状に繰り返し並べることができる。
画像の読み込みや保存などNumPyを使った画像処理の基礎については以下の記事を参照。
ここではPillowを使って画像を読み込んでいるが、ndarrayとして読み込むのであればOpenCVなど他のライブラリを使っても同じ。
カラー画像の場合、読み込んだndarrayのshape(形状)は(高さ, 幅, 色数)となる。
これをnp.tile()で繰り返すには第二引数repsを(縦の繰り返し数, 横の繰り返し数, 1)とする。末尾の1がない(縦の繰り返し数, 横の繰り返し数)とすると、上述のように(1, 縦の繰り返し数, 横の繰り返し数)とみなされてしまいうまくいかないので注意。
import numpy as np
from PIL import Image
img = np.array(Image.open('data/src/lena_square.png').resize((128, 128)))
print(img.shape)
# (128, 128, 3)
img_tile = np.tile(img, (2, 3, 1))
print(img_tile.shape)
# (256, 384, 3)
Image.fromarray(img_tile).save('data/dst/lena_numpy_tile.jpg')
元の画像。上のサンプルコードでは読み込み時に縮小して使っている。

タイル状に並べた画像。

例のように、np.tile()では同じ画像を繰り返し並べることしかできない。異なる画像をタイル状に並べたい場合は以下の記事を参照。
また、np.tile()を活用した例として、グラデーション画像の生成がある。