note.nkmk.me

Python, NumPyでグラデーション画像を生成

Date: 2017-11-29 / tags: Python, NumPy, 画像処理
スポンサーリンク

NumPyで画像生成

画像をNumPy配列ndarrayとして扱うことで、NumPyの豊富な機能を使って既存の画像を処理したり新たな画像を生成したりすることができる。

画像の読み込み・保存などの詳細は以下の記事参照。

今回はグラデーション画像を生成する。

np.tile()とnp.linspace()を使う

いろいろな方法が考えられるが、今回は、

  • 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]]

グラデーション画像を生成するコード例

縦または横方向に等間隔で増加または減少する二次元のndarrayを生成する関数を準備。このndarrayが単色のグラデーション画像に相当する。

is_horizontalTrueのときは横方向、Falseのときは縦方向に階調が変化する。.Tで転置行列を作って縦方向にしている。

def get_gradation_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
source: nplib.py

これを三次元に拡張する。各色に対するstart, stop, is_horizontalをリストで設定し、上の二次元版を呼び出してそれぞれのチャンネルにグラデーション画像を生成する。

def get_gradation_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_gradation_2d(start, stop, width, height, is_horizontal)

    return result
source: nplib.py

実際にグラデーション画像を生成し保存する。

array = get_gradation_3d(512, 256, (0, 0, 0), (255, 255, 255), (True, True, True))
Image.fromarray(np.uint8(array)).save('data/dst/gradation_h.jpg', quality=95)

NumPyで生成したグラデーション画像 横

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

NumPyで生成したグラデーション画像 縦

RGB毎にグラデーション方向を変えたりすることも可能。

array = get_gradation_3d(512, 256, (0, 0, 192), (255, 255, 64), (True, False, False))
Image.fromarray(np.uint8(array)).save('data/dst/gradation_color.jpg', quality=95)

NumPyで生成したグラデーション画像 カラー

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事