Reproduire des images avec des primitives géométriques.
Une image cible est fournie comme entrée. L'algorithme essaie de trouver la forme la plus optimale qui peut être dessinée pour minimiser l'erreur entre l'image cible et l'image dessinée. Il répète ce processus, ajoutant une forme à la fois . Environ 50 à 200 formes sont nécessaires pour atteindre un résultat reconnaissable mais artistique et abstrait.
Maintenant disponible en tant qu'application Mac native!
https://primitive.lol/
Suivez @primitivepic sur Twitter pour voir une nouvelle image primitive toutes les 30 minutes!
Le bot Twitter recherche des photos intéressantes à l'aide de l'API Flickr, exécute l'algorithme à l'aide de paramètres randomisés et publie l'image à l'aide de l'API Twitter.
Vous pouvez tweeter une image au bot et il le traitera pour vous.
Exécutez-le sur vos propres images! Tout d'abord, installez Go.
go get -u github.com/fogleman/primitive
primitive -i input.png -o output.png -n 100
De petites images d'entrée doivent être utilisées (comme 256x256px). Vous n'avez pas besoin de détail de toute façon et le code s'exécutera plus rapidement.
Drapeau | Défaut | Description |
---|---|---|
i | n / A | fichier de saisie |
o | n / A | fichier de sortie |
n | n / A | nombre de formes |
m | 1 | MODE: 0 = combo, 1 = triangle, 2 = rect, 3 = ellipse, 4 = cercle, 5 = rotatedrect, 6 = beziers, 7 = rotatedellipse, 8 = polygone |
rep | 0 | Ajouter n des formes supplémentaires chaque itération avec une recherche réduite (principalement bon pour les beziers) |
nth | 1 | Enregistrer chaque nème trame (seulement lorsque %d est en chemin de sortie) |
r | 256 | redimensionner les grandes images d'entrée à cette taille avant le traitement |
s | 1024 | Taille de l'image de sortie |
a | 128 | Color Alpha (utilisez 0 pour laisser l'algorithme choisir alpha pour chaque forme) |
bg | AVG | Démarrage de la couleur d'arrière-plan (hex) |
j | 0 | Nombre de travailleurs parallèles (par défaut utilise tous les noyaux) |
v | désactivé | sortie verbale |
vv | désactivé | sortie très verbeuse |
Selon l'extension de nom de fichier de sortie fournie, vous pouvez produire différents types de sortie.
PNG
: sortie rasterJPG
: sortie rasterSVG
: sortie vectorielleGIF
: sortie animée montrant les formes ajoutées - nécessite ImageMagick (en particulier la commande convert
) Pour les sorties PNG et SVG, vous pouvez également inclure %d
, %03d
, etc. dans le nom de fichier. Dans ce cas, chaque trame sera enregistrée séparément.
Vous pouvez utiliser le Flag -o
plusieurs fois. De cette façon, vous pouvez enregistrer à la fois un PNG et un SVG, par exemple.
Ce GIF démontre la nature itérative de l'algorithme, tentant de minimiser l'erreur quadratique moyenne en ajoutant une forme à la fois. (Utilisez un fichier de sortie ".gif" pour en générer un vous-même!)
Étant donné que l'algorithme a un composant aléatoire, vous pouvez l'exécuter plusieurs fois par rapport à la même image d'entrée pour donner vie à une image statique.
Si vous êtes prêt à vous piéger dans le code, vous pouvez appliquer des contraintes sur les formes pour produire des résultats encore plus intéressants. Ici, les rectangles sont limités à pointer vers le soleil sur cette image d'un coucher de soleil pyramide.
La matrice ci-dessous montre des triangles, des ellipses et des rectangles à 50, 100 et 200 itérations chacun.
Disons que nous avons une Target Image
. C'est ce que nous travaillons à recréer. Nous commençons par une toile vierge, mais nous la remplissons d'une seule couleur unie. Actuellement, il s'agit de la couleur moyenne de l' Target Image
. Nous appelons cette nouvelle toile vierge l' Current Image
. Maintenant, nous commençons à évaluer les formes. Pour évaluer une forme, nous le dessinons sur l' Current Image
, produisant une New Image
. Cette New Image
est comparée à l' Target Image
pour calculer un score. Nous utilisons l'erreur de carré à moyens de racine pour le score.
Current Image + Shape => New Image
RMSE(New Image, Target Image) => Score
Les formes sont générées au hasard. Nous pouvons générer une forme aléatoire et le marquer. Ensuite, nous pouvons muter la forme (en peaufinant un sommet de triangle, en peaufinant un rayon ou un centre d'ellipse, etc.) et le marquer à nouveau. Si la mutation améliorait le score, nous le gardons. Sinon, nous retournons à l'état précédent. La répétition de ce processus est connue sous le nom d'escalade en colline. L'escalade est susceptible de rester coincé dans des minima locaux, nous le faisons donc en fait à plusieurs moments différents avec plusieurs formes de départ différentes. Nous pouvons également générer n formes aléatoires et choisir la meilleure avant de commencer l'escalade. Le recuit simulé est une autre bonne option, mais dans mes tests, j'ai trouvé la technique d'escalade de la colline tout aussi bonne et plus rapide, du moins pour ce problème particulier.
Une fois que nous avons trouvé une forme de bonne score, nous l'ajoutons à l' Current Image
, où elle restera inchangée. Ensuite, nous recommençons le processus pour trouver la forme suivante à dessiner. Ce processus est répété autant de fois que souhaité.
Les primitives suivantes sont soutenues:
Plus de formes peuvent être ajoutées en implémentant l'interface suivante:
type Shape interface {
Rasterize () [] Scanline
Copy () Shape
Mutate ()
Draw ( dc * gg. Context )
SVG ( attrs string ) string
}
Ce projet a été initialement inspiré par le travail populaire et excellent de Roger Johansson - Programmation génétique: évolution de Mona Lisa. Depuis qu'il a vu cet article quand il était assez nouveau, j'ai bricolé ce problème ici et là au fil des ans. Mais ce n'est que maintenant que je suis satisfait de mes résultats.
Il convient de noter qu'il existe des différences significatives dans ma mise en œuvre par rapport à l'œuvre originale de Roger. Le mien n'est pas un algorithme génétique. Le mien fonctionne uniquement sur une forme à la fois. Le mien est beaucoup plus rapide (AFAIK) et prend en charge de nombreux types de formes.
Voici d'autres exemples de photos intéressantes trouvées sur Flickr.