Reproducción de imágenes con primitivas geométricas.
Se proporciona una imagen objetivo como entrada. El algoritmo intenta encontrar la forma más óptima que se puede dibujar para minimizar el error entre la imagen de destino y la imagen dibujada. Repita este proceso, agregando una forma a la vez . Se necesitan alrededor de 50 a 200 formas para alcanzar un resultado reconocible pero artístico y abstracto.
¡Ahora disponible como una aplicación Mac nativa!
https://primitivo.lol/
¡Siga @PrimitivePic en Twitter para ver una nueva imagen primitiva cada 30 minutos!
El bot de Twitter busca fotos interesantes usando la API de Flickr, ejecuta el algoritmo usando parámetros aleatorios y publica la imagen usando la API de Twitter.
Puede tuitear una imagen al bot y la procesará para usted.
¡Ejecutarlo en sus propias imágenes! Primero, instale Go.
go get -u github.com/fogleman/primitive
primitive -i input.png -o output.png -n 100
Se deben usar pequeñas imágenes de entrada (como 256x256px). De todos modos, no necesita el detalle y el código se ejecutará más rápido.
Bandera | Por defecto | Descripción |
---|---|---|
i | n / A | archivo de entrada |
o | n / A | archivo de salida |
n | n / A | número de formas |
m | 1 | Modo: 0 = combo, 1 = Triángulo, 2 = Rect, 3 = Ellipse, 4 = Círculo, 5 = RotatedRect, 6 = Beziers, 7 = Rotatedellipse, 8 = Polígono |
rep | 0 | Agregue n formas adicionales cada iteración con búsqueda reducida (en su mayoría buena para los beziers) |
nth | 1 | Guarde cada enésimo cuadro (solo cuando %d está en la ruta de salida) |
r | 256 | Dice el tamaño de las imágenes de entrada grandes a este tamaño antes del procesamiento |
s | 1024 | tamaño de imagen de salida |
a | 128 | color alfa (use 0 para dejar que el algoritmo elija alfa para cada forma) |
bg | aviso | Color de fondo inicial (hex) |
j | 0 | Número de trabajadores paralelos (el valor predeterminado utiliza todos los núcleos) |
v | apagado | salida detallada |
vv | apagado | salida muy detallada |
Dependiendo de la extensión del nombre de archivo de salida proporcionada, puede producir diferentes tipos de salida.
PNG
: salida de tramaJPG
: salida de tramaSVG
: salida vectorialGIF
: salida animada que muestra formas agregadas - requiere imagemagick (específicamente el comando convert
) Para las salidas PNG y SVG, también puede incluir %d
, %03d
, etc. en el nombre de archivo. En este caso, cada cuadro se guardará por separado.
Puede usar la bandera -o
varias veces. De esta manera, puede guardar un PNG y un SVG, por ejemplo.
Este GIF demuestra la naturaleza iterativa del algoritmo, intentando minimizar el error cuadrático medio agregando una forma a la vez. (¡Use un archivo de salida ".gif" para generar uno usted mismo!)
Dado que el algoritmo tiene un componente aleatorio, puede ejecutarlo contra la misma imagen de entrada varias veces para dar vida a una imagen estática.
Si está dispuesto a incursionar en el código, puede imponer restricciones en las formas para producir resultados aún más interesantes. Aquí, los rectángulos están limitados para apuntar hacia el sol en esta imagen de una pura puesta de sol.
La siguiente matriz muestra triángulos, elipses y rectángulos a 50, 100 y 200 iteraciones cada uno.
Digamos que tenemos una Target Image
. Esto es lo que estamos trabajando para recrear. Comenzamos con un lienzo en blanco, pero lo llenamos con un solo color sólido. Actualmente, este es el color promedio de la Target Image
. Llamamos a este nuevo lienzo en blanco la Current Image
. Ahora, comenzamos a evaluar formas. Para evaluar una forma, la dibujamos encima de la Current Image
, produciendo una New Image
. Esta New Image
se compara con la Target Image
para calcular una puntuación. Utilizamos el error de cuadro de raíz para la puntuación.
Current Image + Shape => New Image
RMSE(New Image, Target Image) => Score
Las formas se generan al azar. Podemos generar una forma aleatoria y anotarla. Luego podemos mutar la forma (ajustando un vértice de triángulo, ajustando un radio o centro de elipse, etc.) y anotarlo nuevamente. Si la mutación mejoró la puntuación, la mantenemos. De lo contrario, volvemos al estado anterior. Repetir este proceso se conoce como escalada en la colina. La escalada es propensa a quedarse atascado en los mínimos locales, por lo que en realidad hacemos esto muchos momentos diferentes con varias formas iniciales diferentes. También podemos generar n formas aleatorias y elegir la mejor antes de comenzar la escalada. El recocido simulado es otra buena opción, pero en mis pruebas encontré la técnica de escalada de la colina igual de buena y más rápida, al menos para este problema en particular.
Una vez que hemos encontrado una forma de buena puntuación, la agregamos a la Current Image
, donde permanecerá sin cambios. Luego comenzamos el proceso nuevamente para encontrar la siguiente forma para dibujar. Este proceso se repite tantas veces como desee.
Se apoyan las siguientes primitivas:
Se pueden agregar más formas implementando la siguiente interfaz:
type Shape interface {
Rasterize () [] Scanline
Copy () Shape
Mutate ()
Draw ( dc * gg. Context )
SVG ( attrs string ) string
}
Este proyecto se inspiró originalmente en el trabajo popular y excelente de Roger Johansson - Programación genética: Evolución de Mona Lisa. Desde que vi ese artículo cuando era bastante nuevo, he jugado con este problema aquí y allá a lo largo de los años. Pero solo ahora estoy satisfecho con mis resultados.
Cabe señalar que hay diferencias significativas en mi implementación en comparación con el trabajo original de Roger. El mío no es un algoritmo genético. El mío solo opera en una forma a la vez. El mío es mucho más rápido (AFAIK) y admite muchos tipos de formas.
Aquí hay más ejemplos de fotos interesantes que se encuentran en Flickr.