Pythonで美しいグラデーション画像を生成!NumPyで色の変化を自在に操る
データ可視化や画像処理、デザインといった分野では、滑らかな色の移り変わりを持つグラデーション画像がよく利用されます。Pythonでグラデーション画像を生成するには、数値計算ライブラリであるNumPyが非常に強力なツールとなります。NumPyの配列操作とブロードキャスト機能を使えば、複雑な色の変化も簡潔なコードで表現できます。この記事では、NumPyを使って線形グラデーション(水平・垂直)と放射状グラデーション画像を生成する方法について、具体的なサンプルコードを交えながら詳しく解説します。
画像データとNumPy配列の基本
デジタル画像は、画素(ピクセル)の集まりであり、各画素は色情報を数値で持ちます。
-
グレースケール画像:各画素が明るさの値(0〜255)を持つ2次元配列。
-
カラー画像(RGB):各画素が赤(R)、緑(G)、青(B)の3つのチャンネルの値(それぞれ0〜255)を持つ3次元配列(通常
(高さ, 幅, 3)の形状)。
NumPyは、このような数値データを効率的に扱うための最適な構造を提供します。グラデーションの生成は、この画素値を数学的に計算して配列に割り当てることで実現されます。
1. 線形グラデーションの生成
線形グラデーションは、一方向に向かって色が均一に変化するグラデーションです。ここでは、水平方向と垂直方向のグラデーションを作成します。
1-1. 水平グラデーション(白から黒)
画像の左端から右端に向かって、白から黒へ(またはその逆へ)色が変化するグラデーションを生成します。
サンプルコード
import numpy as np
from PIL import Image
# 画像サイズを設定
width, height = 400, 200
# 水平グラデーション (白から黒へ)
# 0から255までの値を幅の数だけ生成し、2次元に拡張
horizontal_gradient_values = np.linspace(255, 0, width, dtype=np.uint8)
# 各行に同じグラデーションを適用するためにブロードキャスト
horizontal_gradient_img_np = np.tile(horizontal_gradient_values, (height, 1))
# NumPy配列をPillow画像に変換して保存
# グレースケール画像は 'L' モードで保存
img_pil_h = Image.fromarray(horizontal_gradient_img_np, mode='L')
img_pil_h.save('horizontal_gradient.png')
print("水平グラデーション画像を 'horizontal_gradient.png' として保存しました。")
1-2. 垂直グラデーション(黒から白)
画像の上端から下端に向かって、黒から白へ色が変化するグラデーションを生成します。
サンプルコード
import numpy as np
from PIL import Image
# 画像サイズを設定
width, height = 200, 400
# 垂直グラデーション (黒から白へ)
# 0から255までの値を高さの数だけ生成し、2次元に拡張
vertical_gradient_values = np.linspace(0, 255, height, dtype=np.uint8)
# 各列に同じグラデーションを適用するためにブロードキャスト
vertical_gradient_img_np = np.tile(vertical_gradient_values[:, np.newaxis], (1, width))
# NumPy配列をPillow画像に変換して保存
img_pil_v = Image.fromarray(vertical_gradient_img_np, mode='L')
img_pil_v.save('vertical_gradient.png')
print("垂直グラデーション画像を 'vertical_gradient.png' として保存しました。")
2. 放射状グラデーションの生成
放射状グラデーションは、中心から外側に向かって色が変化するグラデーションです。
サンプルコード(中心から外側へ暗くなるグラデーション)
中心からの距離に基づいて明るさの値を計算します。
import numpy as np
from PIL import Image
# 画像サイズを設定
width, height = 300, 300
center_x, center_y = width // 2, height // 2
# 各ピクセルの座標グリッドを作成
x = np.arange(width) - center_x
y = np.arange(height) - center_y
X, Y = np.meshgrid(x, y)
# 中心からの距離を計算 (ユークリッド距離)
distance = np.sqrt(X**2 + Y**2)
# 距離を0-255の範囲に正規化(例: 最も遠い角までの距離を最大値とする)
max_distance = np.sqrt(center_x**2 + center_y**2) # 中心から角までの距離
normalized_distance = (distance / max_distance) * 255
# グラデーションを反転(中心が白、外側が黒)またはそのまま(中心が黒、外側が白)
# ここでは中心から外側へ暗くなるようにする
radial_gradient_np = (255 - normalized_distance).astype(np.uint8)
# NumPy配列をPillow画像に変換して保存
img_pil_r = Image.fromarray(radial_gradient_np, mode='L')
img_pil_r.save('radial_gradient.png')
print("放射状グラデーション画像を 'radial_gradient.png' として保存しました。")
3. カラーグラデーションへの応用
上記の原理は、カラーグラデーションにも応用できます。各R, G, Bチャンネルに対して独立したグラデーションを生成し、それらを組み合わせて3次元配列を作成します。
サンプルコード(青から黄緑への水平グラデーション)
import numpy as np
from PIL import Image
width, height = 400, 200
# 青 (0, 0, 255) から 黄緑 (173, 255, 47) へ変化させる例
# 各チャンネルの値を線形補間
r_channel = np.linspace(0, 173, width, dtype=np.uint8)
g_channel = np.linspace(0, 255, width, dtype=np.uint8)
b_channel = np.linspace(255, 47, width, dtype=np.uint8)
# 各チャンネルのグラデーションを高さ方向に複製
r_gradient = np.tile(r_channel, (height, 1))
g_gradient = np.tile(g_channel, (height, 1))
b_gradient = np.tile(b_channel, (height, 1))
# RGBチャンネルを結合してカラー画像配列を生成
# shape: (height, width, 3)
color_gradient_img_np = np.stack([r_gradient, g_gradient, b_gradient], axis=-1)
# NumPy配列をPillow画像に変換して保存
img_pil_color = Image.fromarray(color_gradient_img_np, mode='RGB')
img_pil_color.save('color_gradient.png')
print("カラーグラデーション画像を 'color_gradient.png' として保存しました。")
まとめ
NumPyを使ってグラデーション画像を生成することは、配列操作の強力さとPythonの柔軟性を示す良い例です。
-
線形グラデーション:
np.linspace()で色の範囲を定義し、np.tile()やブロードキャストで画像を構築します。 -
放射状グラデーション:
np.meshgrid()で座標グリッドを作成し、中心からの距離に基づいて画素値を計算します。 -
カラーグラデーション: 各RGBチャンネルに対して独立したグラデーションを生成し、
np.stack()で結合します。
これらのテクニックは、データ可視化における背景作成、UIデザイン要素の生成、または機械学習モデルのテスト画像生成など、様々なクリエイティブな用途に応用できます。NumPyの配列操作をマスターして、Pythonで美しいグラデーション画像を自在に生成してみてください!🌈
