100行未満のコードで手続き型アートを作成する方法





ジェネレーティブアート(ジェネレーティブアートまたはプロシージャルアート)は、これまでに見たことのない人を怖がらせることができます。 要するに、これは文字通り自分自身を作成するアートの概念であり、初めてハードコアプログラミングの知識を必要としません。 そこで、私たちはテープを少し希釈することに決めました。



ジェネレーティブアートとは



これは、人ではなくオブジェクトについて独自の決定を行うシステムの結果です。 システムには、ルールとチャンスがあれば、単一のPythonプログラムと同じくらい簡単にできます。



プログラミングを使用すると、ルールや制限を簡単に見つけることができます。 これには条件文があります。 しかし、これらのルールを作成して面白いものを作成する方法を見つけることは、それほど簡単ではないかもしれません。





コンウェイの人生のゲーム



ConwayのGame of Lifeは、システム内の各セルの「誕生」と「死」を定義する4つの単純なルールの有名なセットです。 各ルールは、各世代を通じてシステムを進める上で役割を果たします。 ルールはシンプルで理解しやすいものですが、複雑なパターンがすぐに現れ、最終的には刺激的な結果を生み出します。



ルールは何か面白いものの基礎を築くのに責任があるかもしれませんが、ConwayのGame of Lifeのような刺激的なものでさえ予測可能です。 4つのルールは、各世代の決定要因です。 したがって、予期しない結果を得るには、セルの初期状態にランダム化を導入する必要があります。 ランダムマトリックスから始めて、各実行はルールを変更することなく一意になります。



ジェネレーティブアートの最良の例は、予測可能性とランダム性の組み合わせを見つけて、統計的に再現できない興味深いものを作成するものです。



なぜこれを試してみるべきですか?



ジェネレーティブアートは、必ずしもあなたが時間をかけたいものとは限りません。 しかし、あなたがそれに取り組むことに決めたなら、あなたは次の利点を頼りにすることができます:





どこから始めますか?



ジェネレーティブアートの開始は、他のプロジェクトの開始と同じプロセスです。 最も重要なステップは、アイデアを思いつくか、さらなる開発のためにそれを見つけることです。 目標を設定したら、それを達成するために作業を開始できます。



私の創造的なプロジェクトの大部分はPythonです。 これは、画像処理に役立つ多くの便利なパッケージを備えた非常にシンプルな言語です。 たとえば、 Pillow



幸いなことに、どこから始めるべきかを長く探す必要はありません。以下でコードを共有します。



スプライトジェネレーター



このプロジェクトは、JavaScriptで記述されたスプライトジェネレーターの投稿を見たときに始まりました。 このプログラムは、ランダムカラーオプションで5×5ピクセルのアートスプライトを作成し、その結果はマルチカラースペースインベーダーに似ていました。



Pythonで画像処理を練習したかったので、自分でこの概念を再現することにしました。 さらに、元のプロジェクトはスプライトのサイズが非常に限られていたため、拡張できると考えました。 そして、スプライトのサイズだけでなく、その数、さらには画像のサイズも示したいと思います。



ここに私のプログラムからの2つの異なる結果があります:





7x7-30–1900





43x43-6–1900



これらの2つのイメージはまったく同じではありませんが、両方とも同じシステムの結果です。 スプライトは複雑でランダムに生成されるため、同じ引数を使用しても、これらのイメージが永久に残る可能性が高いという事実は言うまでもありません。 大好きです。



環境



スプライトジェネレーターに慣れる前に、作業のための小さな基盤を準備する必要があります。



Pythonを使用したことがない場合は、 Python 2.7.10をダウンロードしてください。 最初は、環境の設定に問題がありました。もしそれらに遭遇したら、 仮想環境を見てください。 また、 Pillowもインストールされていることを確認してください。



環境を設定した後、拡張子.pyのファイルにコードをコピーして、次のコマンドを実行できます。



python spritething.py [SPRITE_DIMENSIONS] [NUMBER] [IMAGE_SIZE]
      
      





たとえば、スプライトの最初のマトリックスを作成するコマンドは次のようになります。



 python spritething.py 7 30 1900
      
      





コード



 import PIL, random, sys from PIL import Image, ImageDraw origDimension = 1500 r = lambda: random.randint(50,215) rc = lambda: (r(), r(), r()) listSym = [] def create_square(border, draw, randColor, element, size): if (element == int(size/2)): draw.rectangle(border, randColor) elif (len(listSym) == element+1): draw.rectangle(border,listSym.pop()) else: listSym.append(randColor) draw.rectangle(border, randColor) def create_invader(border, draw, size): x0, y0, x1, y1 = border squareSize = (x1-x0)/size randColors = [rc(), rc(), rc(), (0,0,0), (0,0,0), (0,0,0)] i = 1 for y in range(0, size): I *= -1 element = 0 for x in range(0, size): topLeftX = x*squareSize + x0 topLeftY = y*squareSize + y0 botRightX = topLeftX + squareSize botRightY = topLeftY + squareSize create_square((topLeftX, topLeftY, botRightX, botRightY), draw, random.choice(randColors), element, size) if (element == int(size/2) or element == 0): I *= -1; element += I def main(size, invaders, imgSize): origDimension = imgSize origImage = Image.new('RGB', (origDimension, origDimension)) draw = ImageDraw.Draw(origImage) invaderSize = origDimension/invaders padding = invaderSize/size for x in range(0, invaders): for y in range(0, invaders): topLeftX = x*invaderSize + padding/2 topLeftY = y*invaderSize + padding/2 botRightX = topLeftX + invaderSize - padding botRightY = topLeftY + invaderSize - padding create_invader((topLeftX, topLeftY, botRightX, botRightY), draw, size) origImage.save(«Examples/Example-«+str(size)+»x»+str(size)+»-«+str(invaders)+»-«+str(imgSize)+».jpg») if __name__ == «__main__»: main(int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3]))
      
      





この解決策はまだ完全ではありませんが、ジェネレーティブアートの作成には大量のコードは不要であることを示しています。 キーポイントについて説明します。



主な機能は、元の画像の作成とスプライトのサイズの決定から始まります。 2つのforループが各スプライトの境界を決定し、主に画像サイズを要求されたスプライトの数で分割します。 これらの値は、それぞれの座標を決定するために使用されます。



下の画像をご覧ください。 4つの正方形のそれぞれがサイズ1のスプライトであると想像してください。次の関数に渡される境界線は、左上隅と右下隅の座標を参照します。 したがって、左上のスプライトのタプルは(0,0,1,1)になり、右上のタプルは(1,0,2,1)になります。 これらは、各スプライトの正方形の寸法および基本座標として使用されます。





スプライトの境界を決定する例



create_invader関数は、スプライト内の各正方形の境界線を決定します。 境界を決定する同じプロセスがここで適用され、以下に示されますが、完全な画像の代わりに、事前に定義された境界線を使用して内部で作業します。 各正方形のこれらの最終座標は、次の関数でスプライトを描画するために使用されます。





3×3スプライトのブレークダウンの例



色を決定するには、3つのランダムなRGBタプルと3つの黒いタプルの単純な配列を使用して、50%の確率で描画されます。 コードの上部にあるLambda関数は、RGB値を生成します。



この関数の本当のトリックは、対称性を作成することです。 各正方形は要素値に関連付けられています。 次の図は、要素の値が中心に達するにつれて増加し、その後減少する様子を示しています。 一致する要素値を持つ正方形は同じ色で表示されます。





7×7スプライトのストリングの要素値と対称色



create_squarecreate_invaderからパラメーターを取得するため、キューと以前の要素の値を使用して対称性を確保します。 値が最初に表示されるとき、それらの色はキューに配置され、ミラースクエアは色を削除します。





完全な作成プロセス



他の誰かの問題の解決策や曲がったコードを読むのがどれほど難しいかは理解していますが、このアプリケーションを見つけていただければ幸いです。 あなたが私のコードを完全に放棄し、まったく異なる解決策を見つけたら、それはクールです。



おわりに



ジェネレーティブアートは、その可能性を最大限に引き出すのに時間がかかります。 一般に、ジェネレーティブアートよりも有用なプロジェクトが存在する可能性がありますが、これは常に時間の価値があるとは限りません。 しかし、これは多くの楽しみであり、どこで役立つかわからないでしょう。



All Articles