So erstellen Sie prozedurale Kunst in weniger als 100 Codezeilen



Generative Kunst (generative oder prozedurale Kunst) kann Sie abschrecken, wenn Sie sie noch nie zuvor gesehen haben. Kurz gesagt, dies ist ein Kunstkonzept, das sich buchstäblich selbst erschafft und zum ersten Mal keine Hardcore-Programmierkenntnisse erfordert. Also habe ich beschlossen, unser Band ein wenig zu verdünnen, sie fuhren.

Was ist generative Kunst?


Dies ist das Ergebnis eines Systems, das seine eigenen Entscheidungen über ein Objekt anstelle einer Person trifft. Ein System kann so einfach sein wie ein einzelnes Python-Programm, wenn es Regeln und einen Moment des Zufalls hat.

Mit der Programmierung ist es ziemlich einfach, Regeln und Einschränkungen zu finden. Hierfür gibt es bedingte Aussagen. Es ist jedoch möglicherweise nicht so einfach, Wege zu finden, um diese Regeln zu etwas Interessantem zu machen.


Conways Spiel des Lebens

Das Conway-Spiel des Lebens ist ein bekannter Satz von vier einfachen Regeln, die die "Geburt" und den "Tod" jeder Zelle im System definieren. Jede Regel spielt eine Rolle bei der Förderung des Systems durch jede Generation. Obwohl die Regeln einfach und leicht zu verstehen sind, entstehen schnell komplexe Muster, die letztendlich zu aufregenden Ergebnissen führen.

Die Regeln mögen dafür verantwortlich sein, den Grundstein für etwas Interessantes zu legen, aber selbst etwas so Aufregendes wie Conways Spiel des Lebens ist vorhersehbar. Die vier Regeln sind die bestimmenden Faktoren für jede Generation. Um unerwartete Ergebnisse zu erzielen, müssen Sie daher im Anfangszustand der Zellen eine Randomisierung einführen. 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 solche, die eine Kombination aus Vorhersagbarkeit und Zufälligkeit finden, um etwas Interessantes zu schaffen, das statistisch unmöglich zu wiederholen ist.

Warum sollten Sie das versuchen?


Generative Kunst ist nicht immer das, wofür Sie Zeit verbringen möchten. Wenn Sie sich jedoch dazu entschließen, 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 Eingabe 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 ja, oder zumindest sehe ich es nicht. Momentan gibt es in meinem Wohnzimmer mehrere Poster mit Drucken meiner prozeduralen Kunst. Und ich mag es, dass dies durch Code gemacht wird.
  • Attraktive Designs. Jeder hatte die Erfahrung, jemandem ein persönliches Projekt zu erklären, möglicherweise 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 der gleiche Prozess wie bei jedem 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 beginnen, an dessen Erreichung zu arbeiten.

Die meisten meiner kreativen Projekte sind in Python. 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 suchen, wo Sie anfangen sollen - unten werde ich meinen Code teilen.

Sprite-Generator


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

Ich wollte die Bildverarbeitung in Python üben und habe mich daher entschlossen, dieses Konzept selbst neu zu erstellen. Außerdem dachte ich, ich könnte es erweitern, da das ursprüngliche Projekt in der Größe der Sprites sehr begrenzt 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 aus meinem Programm:


7x7-30-1900


43x43-6-1900

Diese beiden Bilder unterscheiden sich vollständig voneinander, sind jedoch beide das Ergebnis desselben Systems. Ganz zu schweigen von der Tatsache, dass aufgrund der Komplexität und der zufälligen Erzeugung von Sprites eine hohe Wahrscheinlichkeit besteht, dass diese Bilder selbst mit denselben Argumenten für immer einzigartig sein werden. Ich liebe es

Umgebung


Bevor Sie sich mit dem Sprite-Generator vertraut machen, sollten Sie eine kleine Grundlage für den Job vorbereiten.

Wenn Sie zuvor noch nicht mit Python gearbeitet haben, laden Sie Python 2.7.10 herunter. Zuerst hatte ich Probleme beim Einrichten der Umgebung. Wenn Sie auch auf diese stoßen, schauen Sie in virtuelle 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 Sprite-Matrix lautet beispielsweise:

 python spritething.py 7 30 1900 

Code


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

Diese Lösung ist noch lange nicht perfekt, zeigt jedoch, dass für die Erstellung generativer Kunst nicht viel Code erforderlich ist. Ich werde die wichtigsten Punkte erläutern.

Die Hauptfunktion beginnt mit der Erstellung des Originalbilds und der Bestimmung der Größe der Sprites. Zwei for- Schleifen sind für die Bestimmung des Rahmens jedes Sprites verantwortlich und teilen die Bildgröße im Wesentlichen durch die Anzahl der angeforderten Sprites. 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, jedes der vier Quadrate ist ein Sprite mit Größe 1. Der Rand, der an die nächste Funktion übergeben wird, bezieht sich auf die Koordinaten der oberen linken und unteren rechten Ecke. Das Tupel im oberen linken Sprite ist also (0,0,1,1) und das Tupel im oberen rechten Sprite ist (1,0,2,1). Sie werden als Bemaßungen und Basiskoordinaten für die Quadrate jedes Sprites verwendet.


Beispiel für die Definition von Sprite-Rändern

Die Funktion create_invader definiert den Rand für jedes Quadrat innerhalb des Sprites. Der gleiche Prozess zum Bestimmen der Grenze wird hier angewendet und wird unten dargestellt. Nur anstelle des vollständigen Bildes verwenden wir einen vordefinierten Rand für die Arbeit im Inneren. Diese endgültigen Koordinaten für jedes Quadrat werden in der nächsten Funktion zum Zeichnen eines Sprites verwendet.


Beispiel für einen 3 × 3-Sprite-Zusammenbruch

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

Der eigentliche Trick dieser Funktion besteht darin, Symmetrie zu erzeugen. Jedes Quadrat ist einem Elementwert zugeordnet. Die folgende Abbildung zeigt, wie sich die Werte der Elemente erhöhen, wenn sie die Mitte erreichen, und dann abnehmen. Quadrate mit übereinstimmenden Elementwerten werden in derselben Farbe angezeigt.


Elementwerte und symmetrische Farben für eine Zeichenfolge in einem 7 × 7-Sprite

Da create_square seine Parameter von create_invader erhält , werden die Werte für die Warteschlange und die vorherigen Elemente verwendet, um die Symmetrie sicherzustellen. Wenn Werte zum ersten Mal angezeigt werden, werden ihre Farben in die Warteschlange gestellt, und Spiegelquadrate entfernen die Farben.


Schließen Sie den Erstellungsprozess ab

Ich verstehe, wie schwierig es ist, die Lösung eines anderen für das Problem und den krummen Code zu lesen, aber ich hoffe, Sie finden diese Anwendung. Es wird cool sein, wenn Sie meinen Code vollständig aufgeben und eine völlig andere Lösung finden.

Fazit


Generative Kunst braucht Zeit, um ihr volles Potenzial auszuschöpfen. Im Allgemeinen gibt es möglicherweise nützlichere Projekte als generative Kunst, was nicht immer die Zeit wert ist. Aber es macht viel Spaß und man weiß nie, wo es nützlich sein kann.

Source: https://habr.com/ru/post/de429078/


All Articles