So erstellen Sie prozedurale Kunst in weniger als 100 Codezeilen

Ursprünglicher Autor: Eric Davidson
  • Übersetzung


Generative Kunst (generative oder prozedurale Kunst) kann Sie abschrecken, wenn Sie sie noch nie zuvor gesehen haben. Kurz gesagt, dies ist der Begriff der Kunst, der sich buchstäblich selbst kreiert und zum ersten Mal keine Hardcore-Programmierkenntnisse erfordert. Daher entschied ich mich, unser Klebeband etwas zu verdünnen, fuhr.

Was ist generative Kunst?


Dies ist das Ergebnis eines Systems, das seine eigene Entscheidung über das Subjekt und nicht über die Person trifft. Ein System kann so einfach wie ein einzelnes Python-Programm sein, wenn es Regeln und einen Moment der Zufälligkeit hat.

Mit dem Programmieren ist es ziemlich einfach, Regeln und Einschränkungen aufzustellen. Dafür gibt es bedingte Operatoren. Es kann jedoch nicht so einfach sein, Wege zu finden, mit denen diese Regeln interessant werden.


Conways Spiel des Lebens

Das Spiel Conways Spiel des Lebens besteht aus vier einfachen Regeln, in denen "Geburt" und "Tod" jeder Zelle des Systems definiert werden. Jede Regel spielt eine Rolle bei der Weiterentwicklung des Systems durch jede Generation. Obwohl die Regeln einfach und leicht verständlich sind, entstehen schnell komplexe Muster, die letztendlich zu aufregenden Ergebnissen führen.

Die Regeln können dafür verantwortlich sein, die Grundlagen für etwas Interessantes zu schaffen, aber auch etwas so Aufregendes wie Conways Game of Life ist vorhersehbar. Vier Regeln sind die bestimmenden Faktoren für jede Generation. Um unerwartete Ergebnisse zu erhalten, müssen Sie daher im Anfangsstatus der Zellen eine Randomisierung eingeben. Beginnend mit einer Zufallsmatrix ist jede Ausführung eindeutig, ohne dass die Regeln geändert werden müssen.

Die besten Beispiele für generative Kunst sind diejenigen, die eine Kombination aus Vorhersagbarkeit und Chance finden, um etwas Interessantes zu schaffen, das sich statistisch nicht wiederholen lässt.

Warum sollten Sie das versuchen?


Generative Kunst wird nicht immer das sein, wofür Sie Zeit verbringen möchten. Wenn Sie sich jedoch dafür entscheiden, daran zu arbeiten, können Sie auf die folgenden Vorteile zählen:

  • Erfahrung Generative Kunst ist eine weitere Gelegenheit, neue und alte Fähigkeiten zu verbessern. Es kann als Input für die Erarbeitung von Konzepten wie Algorithmen, Datenstrukturen und sogar neuen Sprachen dienen.
  • Greifbare Ergebnisse. In der Programmierung sehen wir selten die physischen Ergebnisse unserer Bemühungen. Na oder zumindest sehe ich es nicht. Jetzt in meinem Wohnzimmer gibt es mehrere Poster mit Drucken meiner prozeduralen Kunst. Und ich finde es toll, dass dies durch Code geschieht.
  • Attraktive Designs. Jeder hatte die Erfahrung, jemandem ein persönliches Projekt zu erklären, vielleicht sogar während eines Interviews. Generative Kunst spricht für sich. Die meisten Menschen werden die Ergebnisse zu schätzen wissen, auch wenn sie die Methoden nicht vollständig verstehen können.

Wo soll ich anfangen?


Der Einstieg in die generative Kunst ist derselbe Prozess wie der Beginn der Arbeit mit einem anderen Projekt. Der wichtigste Schritt ist, eine Idee zu entwickeln oder für die weitere Entwicklung zu finden. Sobald Sie ein Ziel haben, können Sie daran arbeiten.

Die meisten meiner kreativen Projekte werden in Python ausgeführt. Es ist eine ziemlich einfache Sprache mit vielen nützlichen Paketen, die bei der Bildverarbeitung helfen. Zum Beispiel Kissen .

Glücklicherweise müssen Sie nicht lange nach dem Start suchen. Ich gebe unten meinen Code weiter.

Sprite-Generator


Dieses Projekt begann, als ich einen Beitrag mit einem in JavaScript geschriebenen Sprite-Generator sah. Das Programm erstellte 5 × 5 Pixel-Sprites mit zufälligen Farboptionen. Das Ergebnis ähnelte mehrfarbigen Eindringlingen.

Ich wollte die Bildverarbeitung in Python üben, also entschloss ich mich, dieses Konzept selbst neu zu erstellen. Außerdem dachte ich, dass ich es erweitern könnte, da das ursprüngliche Projekt in der Größe der Sprites stark eingeschränkt war. Und ich möchte nicht nur die Größe der Sprites angeben, sondern auch deren Anzahl und sogar die Größe des Bildes.

Hier sind zwei verschiedene Ergebnisse meines Programms:


7x7–30–1900


43x43–6–1900

Diese beiden Bilder unterscheiden sich vollständig voneinander, sind aber beide das Ergebnis desselben Systems. Ganz zu schweigen von der Tatsache, dass aufgrund der Komplexität und der zufälligen Generierung von Sprites die Wahrscheinlichkeit hoch ist, dass diese Bilder mit den gleichen Argumenten für immer einzigartig bleiben. Ich liebe es

Umgebung


Vor dem Treffen mit dem Generator von Sprites sollte eine kleine Grundlage für die Arbeit vorbereitet werden.

Wenn Sie noch nicht mit Python gearbeitet haben, laden Sie Python 2.7.10 herunter . Zuerst hatte ich Probleme mit der Einrichtung der Umgebung, wenn Sie auch auf sie stoßen - schauen Sie in virtuellen Umgebungen . Und stellen Sie sicher, dass auch Pillow installiert ist.

Nach dem Einrichten der Umgebung können Sie meinen Code in eine Datei mit der Erweiterung .py kopieren und den folgenden Befehl ausführen:

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

Der Befehl zum Erstellen der ersten Sprites-Matrix wäre beispielsweise:

python spritething.py 7301900

Code


import PIL, random, sys
from PIL import Image, ImageDraw
origDimension = 1500
r = lambda: random.randint(50,215)
rc = lambda: (r(), r(), r())
listSym = []
defcreate_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)
defcreate_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 = 1for y in range(0, size):
    I *= -1
    element = 0for 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
defmain(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]))

Diese Lösung ist alles andere als perfekt, aber sie zeigt, dass die Schaffung generativer Kunst keine Tonnen Code erfordert. Ich werde die wichtigsten Punkte erklären.

Die Hauptfunktion beginnt mit der Erstellung des Originalbildes und der Bestimmung der Größe der Sprites. Zwei for- Schleifen sind für die Bestimmung der Grenze jedes Sprites verantwortlich, wobei die Bildgröße im Wesentlichen durch die Anzahl der angeforderten Sprites geteilt wird. Diese Werte werden verwendet, um die Koordinaten für jeden von ihnen zu bestimmen.

Schauen Sie sich das Bild unten an. Stellen Sie sich vor, dass jedes der vier Quadrate ein Sprite mit der Größe 1 ist. Die Grenze, die an die nächste Funktion übergeben wird, bezieht sich auf die Koordinaten der oberen linken und der rechten unteren Ecke. Das Tupel im oberen linken Sprite wird also (0,0,1,1) und das Tupel im oberen rechten Bereich (1,0,2,1). Sie werden als Bemaßungen und Basiskoordinaten für die Quadrate jedes Sprites verwendet.


Beispiel für das Definieren von Sprite-Grenzen-

Funktion create_invaderDefiniert den Rand für jedes Quadrat innerhalb des Sprites. Der gleiche Randdefinitionsprozess wird hier angewendet und nachfolgend dargestellt. Nur anstelle des vollständigen Bildes verwenden wir einen vordefinierten Rahmen, um darin zu arbeiten. Diese endgültigen Koordinaten für jedes Quadrat werden in der nächsten Funktion zum Zeichnen des Sprites verwendet.


Beispiel für das Aufteilen eines 3 × 3-Sprites:

Um die Farbe zu bestimmen, wird ein einfaches Array aus drei zufälligen RGB-Tupeln und drei schwarzen verwendet, um eine 50% ige Chance zu simulieren. Lambda-Funktionen am oberen Rand des Codes sind für die Erzeugung von RGB-Werten verantwortlich.

Der eigentliche Trick dieses Features ist die Erzeugung von Symmetrie. Jedes Quadrat ist mit dem Wert des Elements verknüpft. Die folgende Abbildung zeigt, wie die Werte der Elemente ansteigen, wenn sie die Mitte erreichen, und dann abnehmen. Quadrate mit übereinstimmenden Elementwerten werden in einer Farbe angezeigt.


Elementwerte und symmetrische Farben für die Linie im Sprite 7 × 7.

Da create_square seine Parameter von create_invader bezieht , verwendet es die Warteschlange und die vorherigen Elementwerte, um Symmetrie bereitzustellen. Wenn Werte zum ersten Mal angezeigt werden, werden ihre Farben in eine Warteschlange eingefügt, und Spiegelquadrate entfernen Farben.


Vollständiger Erstellungsprozess

Ich verstehe, wie schwierig es ist, die Lösung einer anderen Person für das Problem und die Codekurve zu lesen, aber ich hoffe, dass Sie dafür eine Verwendung finden werden. Es wird cool, wenn Sie meinen Code vollständig aufgeben und eine völlig andere Lösung finden.

Fazit


Generative Kunst braucht Zeit, um ihr volles Potenzial zu entfalten. Im Allgemeinen gibt es vielleicht mehr nützliche Projekte als generative Kunst, für die es sich nicht immer lohnt, Zeit zu investieren. Aber es macht Spaß und man weiß nie, wo es nützlich sein könnte.

Jetzt auch beliebt: