Python, NumPyでグラデーション画像を生成
画像をNumPy配列ndarrayとして扱うことで、NumPyの豊富な機能を使って既存の画像を処理したり新たな画像を生成したりすることができる。
ここでは、NumPyの関数を利用してグラデーション画像を生成する例を示す。
np.linspace()とnp.tile()- グラデーション画像を生成するコード例
np.linspace()とnp.tile()
いろいろな方法が考えられるが、ここでは以下の流れでグラデーション画像を作成する。
numpy.linspace()で等間隔で増加または減少する一次元配列を生成numpy.tile()でそれを二次元に並べる
グラデーションの方向は縦または横のみ。斜めや放射線状(円形)はサポートしない。
np.linspace()
np.linspace()は開始値start、終了値stop、サンプル数(ポイント数)numを指定すると、等間隔の一次元配列(等差数列)を返す関数。
range()やnp.arange()と違って、間隔(ステップ)を自動的に計算してくれるので便利。
import numpy as np
print(np.linspace(0, 10, 3))
# [ 0. 5. 10.]
print(np.linspace(0, 10, 4))
# [ 0. 3.33333333 6.66666667 10. ]
print(np.linspace(0, 10, 5))
# [ 0. 2.5 5. 7.5 10. ]
start > stopでも適切に処理してくれる。
print(np.linspace(10, 0, 5))
# [10. 7.5 5. 2.5 0. ]
詳細は以下の記事を参照。
np.tile()
np.tile()は配列を縦横に並べる関数。
パターンを繰り返す配列を作成するのに便利。
引数に元の配列と繰り返し回数を指定する。二次元に並べる場合は、繰り返し回数を(行(縦)の繰り返し回数, 列(横)の繰り返し回数)とする。
import numpy as np
a = np.array([0, 1, 2, 3])
print(np.tile(a, 2))
# [0 1 2 3 0 1 2 3]
print(np.tile(a, (3, 2)))
# [[0 1 2 3 0 1 2 3]
# [0 1 2 3 0 1 2 3]
# [0 1 2 3 0 1 2 3]]
print(np.tile(a, (2, 1)))
# [[0 1 2 3]
# [0 1 2 3]]
元の配列が二次元でも同じ。
a = np.array([[11, 12], [21, 22]])
print(np.tile(a, 2))
# [[11 12 11 12]
# [21 22 21 22]]
print(np.tile(a, (3, 2)))
# [[11 12 11 12]
# [21 22 21 22]
# [11 12 11 12]
# [21 22 21 22]
# [11 12 11 12]
# [21 22 21 22]]
print(np.tile(a, (2, 1)))
# [[11 12]
# [21 22]
# [11 12]
# [21 22]]
np.tile()についての詳細は以下の記事を参照。
グラデーション画像を生成するコード例
縦または横方向に等間隔で増加または減少する二次元のndarrayを生成する関数を準備。この関数が返すndarrayが単色のグラデーション画像に相当する。
is_horizontalがTrueのときは横方向、Falseのときは縦方向に階調が変化する。.Tで転置行列を作って縦方向にしている。
def get_gradient_2d(start, stop, width, height, is_horizontal):
if is_horizontal:
return np.tile(np.linspace(start, stop, width), (height, 1))
else:
return np.tile(np.linspace(start, stop, height), (width, 1)).T
これを三次元に拡張する。各色に対するstart, stop, is_horizontalをリストやタプルで設定し、上の二次元版を呼び出してそれぞれのチャンネルにグラデーション画像を生成する。
def get_gradient_3d(width, height, start_list, stop_list, is_horizontal_list):
result = np.zeros((height, width, len(start_list)), dtype=np.float)
for i, (start, stop, is_horizontal) in enumerate(zip(start_list, stop_list, is_horizontal_list)):
result[:, :, i] = get_gradient_2d(start, stop, width, height, is_horizontal)
return result
実際にグラデーション画像を生成し保存する例は以下の通り。
from PIL import Image
array = get_gradient_3d(512, 256, (0, 0, 0), (255, 255, 255), (True, True, True))
Image.fromarray(np.uint8(array)).save('data/dst/gray_gradient_h.jpg', quality=95)

array = get_gradient_3d(512, 256, (0, 0, 0), (255, 255, 255), (False, False, False))
Image.fromarray(np.uint8(array)).save('data/dst/gray_gradient_v.jpg', quality=95)

RGB毎にグラデーション方向を変えたりすることも可能。
array = get_gradient_3d(512, 256, (0, 0, 192), (255, 255, 64), (True, False, False))
Image.fromarray(np.uint8(array)).save('data/dst/color_gradient.jpg', quality=95)
