ジェネラティブアートは、プログラムを活用したアート作品です。最近話題のNFTアートの世界でも注目されています。ジェネラティブアートの組み合わせの仕組みから、ジェネラティブアート作成手順、作成に利用されているPythonコードのロジックを解説します。
ジェネラティブアートとは
ジェネラティブアートは、プログラムを用いて作成されるアート作品のことです。ジェネレーティブアートとも呼ばれることもあります。何もないセロからすべてをプログラムによって生成するアート作品を指す場合もあれば、制作過程の一部にプログラム利用するアート作品を指す場合もあります。この点は文脈から判断してください。
本記事では後者の、制作過程の一部でプログラム利用するアート作品を「ジェネラティブアート」として解説します。
NFTで人気のジェネラティブアート
近年NFTというキーワードをよく耳にしますが、NFTアートの分野でもジェネラティブアートが数多く存在します。共通の構図を持ちながら、デザインや色を少しづつ変化させた作品をプログラムで大量生成し、数千種類・数万種類のアート作品群が売買されています。ここでは、ジェネラティブアートをNFTとして出品している人気のプロジェクトを紹介します。
CryptoPunks
CryptoPunksは、1万点のキャラクターアートです。最も有名な世界的NFTアート作品のひとつです。仮想通貨のレートや売買需要によりますが、1点数千万円レベルの価格で取引されています。
OpenSea; https://opensea.io/collection/cryptopunks
BORED APE YACHT CLUB (BYAC)
BYACも世界トップレベルで人気のある10000万点のNFTアートです。NFT作品がヨットクラブの会員証にもなり、様々な会員限定の特典にアクセスできます。
OpenSea; https://opensea.io/collection/boredapeyachtclub
Murakami.Flowers Official
世界の舞台で活躍する日本人アーティストである村上隆のNFTアートです。村上隆の代表的な花のアートを、ドット絵で表現した作品です。
OpenSea; https://opensea.io/collection/murakami-flowers-2022-official
ジェネラティブアート生成ロジック
少しづつ色やデザインを変えたパーツを準備し、それらをプログラムによって組み合わせることで大量生成を実現しています。例えば以下の図のように、背景・ボディー・マント・スカート・王冠を5種ずつ用意して組み合わせた場合、5の6乗で15,625通りの異なるパターンのアート作品を生成することが可能です。
さらに他のパーツを追加したり、色だけでなく形状を増やしたりすると、さらに膨大な数のアート作品のパターンが生まれます。
Pythonを用いたジェネラティブアートのパーツ組み合わせスクリプトの実行手順
ここでは、具体的にPythonスクリプトを用いたジェネラティブアート作品の流れを解説します。
1. パーツの作成
各パーツを作成します。上記のサンプルの例の場合、背景やボディーといった各パーツのPNGファイルを、ペイントツール等を利用して作成します。重ね合わせできるように、透過背景で各パーツを作成します。
2. プログラムの入手
Githubの以下のリンクから取得します。MITライセンスのプログラムであるため、商用利用やソースコードの改変もOKです。
3. デザインパーツの配置
componentsフォルダに作成したパーツを配置します。一番下のレイヤーは1のフォルダ、その次のレイヤーは2のフォルダとレイヤーごとに格納します。レイヤーが足りない場合はディレクトリを追加し、レイヤーが過剰な場合はディレクトリを削除します。
4. プログラムの実行
generate.pyを実行します。完成ファイルはoutputフォルダに出力されます。
$ python generative_art/generate.py
Pythonスクリプトの解説
generative_art/generate.py
のロジックを解説します。今回のロジックは単純に各レイヤーからランダムで1ファイル取得して組み合わせしています。
プログラムのロジックを理解できると、例えば、選択確率のコントロールによるレア度の演出や、特定のルールに沿ったパーツ同士の組み合わせなどのカスタマイズも可能です。改変OKのソースコードなので、ぜひトライしてみてください。
########## 必要なライブラリの取得 ##########
# randomというのは、各レイヤーからランダムで選択するためのライブラリです。
import random
# OSは、フォルダパスなどを指定するライブラリです。
import os
# PILのImageは、画像ファイルをコントロールするライブラリです。
from PIL import Image
########## リソースフォルダとアウトプットフォルダの指定 ##########
# デザインパーツのフォルダとして、componentsを指定。
components_directory_path = 'components'
# 完成画像のアウトプットフォルダとして、outputを指定。
output_directory_path = 'output'
# それぞれ相対パスで指定しています。
########## componentsフォルダの中の各レイヤーのフォルダ名を取得 ##########
# リスト形式でlayersにセットして、数字の小さい順にソートしています。
# これで、layersには、1,2,3,4,5・・・という数字のみのフォルダ名が入っている状態になります。
layers = os.listdir(components_directory_path)
layers.sort()
########## MAXパターン数の算出 ##########
# 各レイヤーのファイル数を掛け合わせる。
# 具体的には、まずmax_patterns = 1とする。
# 次にレイヤー1から順に、レイヤーのフォルダのパスを生成し、
# そのフォルダ内のファイル数をmax_patternsに乗じる。
# 最終レイヤーまで繰り返すと、全レイヤーのファイル数をかけ合わせた値がmax_patternsに代入される。
max_patterns = 1
for layer in layers:
layer_path = os.path.join(components_directory_path, layer)
max_patterns = max_patterns * len(os.listdir(layer_path))
########## 作成パターン数をユーザーのインプットから取得 ##########
# inputメソッドで取得して、countに代入。
count = input(f'How many files created? Max {max_patterns}\n')
# inputメソッドで取得すると、数字でも文字列になるので、数値型に変換
count = int(count)
########## ユーザー指定数がMAXパターンより大きい場合の処理 ##########
# MAXパターンより大きいとNGなので、
# whileで、countがMAXパターンより大きい場合は、繰り返し値を求め続けるロジックを追加。
while count > max_patterns:
count = input(f'Set a value less than Max {max_patterns}\n')
count = int(count)
########## 画像ファイル生成 ##########
# 初期設定として、
# アウトプットファイル名に含めるIDの桁数を決める。
# IDは0から始まるから、countから1引いて、その数字の桁数がIDの桁数になる。
# これをid_lengthに持たせる。
id_length = len(str(count - 1))
# 組み合わせパターンを記憶しておく用の空のリストを作成。
img_patterns = []
# 繰り返しのカウントアップ用の変数としてnに初期値ゼロをセット。
n = 0
# 作成パターン数回繰り返す。
while n < count:
# 最初のレイヤー(レイヤー1)のフォルダパスを生成。
layer_path = os.path.join(components_directory_path, layers[0])
files = os.listdir(layer_path)
# レイヤー1内の全ファイルからランダムで1ファイル取得。
random_file = random.choice(files)
# ランダムに取得されたファイルのパスを生成。
file_path = os.path.join(layer_path, random_file)
# そのファイルを開いて、imgというオブジェクトに代入。
img = Image.open(file_path)
# 組み合わせパターンとして、リソースパーツのファイル名をインプット。
img_pattern = random_file.split('.')[0]
# 2つ目から最終レイヤーまで繰り返す。
for layer in layers[1:]:
# レイヤーフォルダのパスを生成。
layer_path = os.path.join(components_directory_path, layer)
# レイヤーフォルダ中の全ファイルから1ファイルをランダムで取得。
files = os.listdir(layer_path)
random_file = random.choice(files)
# そのランダムで取得されたファイルのパスを生成。
file_path = os.path.join(layer_path, random_file)
# その画像オブジェクトをadd_imgという変数に代入。
add_img = Image.open(file_path)
# 繰り返し1週前時点の画像の上にペーストする。
# これを最終レイヤーまで繰り返すと、imgにレイヤ1から順に重ねた画像がインプットされる。
img.paste(add_img, add_img)
# 組み合わせパターンに、拡張子を除いたファイル名を追加。
# これを最終レイヤーまで繰り返すと、組み合わせパターンには、
# 各レイヤーのファイル名が配列として格納される。
img_pattern = img_pattern + random_file.split('.')[0]
# 重複チェックで、今までのパターンと同一になっている場合は繰り返し冒頭からリスタート
if img_pattern in img_patterns:
continue;
# 重複がなければ画像ファイルを保存。
else:
# img_patternsにそのパターンを格納
img_patterns.append(img_pattern)
# IDと組み合わせパターンのファイル名を生成し保存
id = str(n).zfill(id_length)
img_file_name = id + '_' + img_pattern + '.png'
img.save(os.path.join(output_directory_path, img_file_name))
n += 1
print(f'File{id} has been generated.')
# 作成パターン数回の繰り返しが完了したらプログラム完了。
print("Complete!")
まとめ
ジェネラティブアートはNFTアートの世界でも人気のジャンルです。ジェネラティブアート作成の仕組みや、実際に作成する手順、手順に用いるプログラムコードの解説を行いました。ぜひご自身のアート作品作成の参考にしてください。
ジェネラティブNFTの作成から販売手順を学びたい場合は、Udemyの「全くの初心者でもできるジェネラティブNFTの作成から出品までのチュートリアル」(私が制作したもの)が参考になります。初心者でもジェネラティブNFTを作成・販売できるように詳しく解説されています。2022/10上旬までコースの無料視聴が可能なので、もし興味があればぜひご視聴ください。→無料期間終了しました。