2010-03-08 8 views
22

Resumen: ¿Puede proponer un algoritmo matemático ish sobre un plano de píxeles que genere una imagen moderadamente interesante, preferiblemente una que en conjunto se parece a algo?Generando imágenes moderadamente interesantes

La historia hasta ahora:

Erase una vez decidí en un esfuerzo por reducir el desperdicio de ciclo en mis (aunque también) numerosos ordenadores, y se dispuso a generar imágenes en un moderadamente manera interesante ; utilizando un PRNG y algunas matemáticas inteligentes para crear imágenes que, en general, se asemejarían a algo.

O al menos, ese era el plan. Como resultado, las matemáticas inteligentes requieren ser un matemático inteligente; esto no soy

Llegué a un punto en el que prefería las líneas rectas (ya que generalmente son los componentes de los que está hecho nuestro mundo), quizás con demasiada fuerza. El resultado es ligeramente interesante; se asemejan, tal vez, las redes de la ciudad, tales como:

City grids, maybe? http://totlandweb.info/imggen.out.png

Ahora la pregunta adecuada: Teniendo en cuenta el código fuente de este pequeño programa; ¿puedes mejorarlo y proponer un método que dé resultados algo más interesantes? (por ejemplo, no las cuadrículas de la ciudad, pero quizás las caras, los animales, la geografía, lo que tiene)

Esto también se entiende como una especie de desafío; Supongo y como tal he establecido algunas reglas completamente arbitrarios e igualmente opcionales:

  1. Los comentarios en el código lo dice todo. Las sugerencias y las "soluciones" deberían editar el algoritmo en sí, no el marco circundante, excepto para corregir los errores que impiden la compilación de la muestra.

  2. El código debe compilarse limpiamente con un compilador C estándar. (Si el ejemplo proporcionado no , oops! Dime, y yo lo arreglo. :)

  3. El método debe, aunque una vez más, esto es opcional, no es necesario para obtener la ayuda de su amigable matemáticas barrio biblioteca, y en general emplea un (P) RNG como su canal de entrada de datos primario .

  4. Soluciones probablemente deberían ser administrables simplemente tirando a cabo todo lo que sea entre las líneas SNIP (los que dicen que no se debe editar encima y por debajo, respectivamente), con una declaración en el sentido de lo que es necesario añadir al preámbulo en particular.

  5. Editar: A veces es fácil olvidar que la gente en Internet no pueden leer mi mente ; pero ahí tienes. El programa debe requerir un mínimo de intervención humana en la generación de las imágenes, excepto para evaluar los resultados y elegir los mejores .

El código requiere un compilador de C y libpng para compilar; No estoy del todo seguro de que el compilador MinGW proporcione las necesidades, pero me sorprendería que no lo hiciera. Para Debian querrá el paquete libpng-dev, y para Mac OS X, querrá las herramientas XCode ..

El código fuente puede ser downloaded here.

Advertencia: Código masivo splurge incoming!

// compile with gcc -o imggen -lpng imggen.c 
// optionally with -DITERATIONS=x, where x is an appropriate integer 
// If you're on a Mac or using MinGW, you may have to fiddle with the linker flags to find the library and includes. 

#include <stdio.h> 
#include <stdlib.h> 
#include <png.h> 

#ifdef ITERATIONS 
#define REPEAT 
#endif // ITERATIONS 

// YOU MAY CHANGE THE FOLLOWING DEFINES 
#define WIDTH 320 
#define HEIGHT 240 

// YOU MAY REPLACE THE FOLLOWING DEFINES AS APPROPRIATE 
#define INK 16384 

void writePNG (png_bytepp imageBuffer, png_uint_32 width, png_uint_32 height, int iteration) { 
    char *fname; 
    asprintf(&fname, "out.%d.png", iteration); 

    FILE *fp = fopen(fname, "wb"); 
    if (!fp) return; 
    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 
    png_infop info_ptr = png_create_info_struct(png_ptr); 
    png_init_io(png_ptr, fp); 
    png_set_filter(png_ptr, PNG_FILTER_TYPE_DEFAULT, PNG_FILTER_NONE); 
    png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); 
    png_set_IHDR(png_ptr, info_ptr, width, height, 8, 
       PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 
    png_set_rows(png_ptr, info_ptr, imageBuffer); 
    png_set_invert_mono(png_ptr); /// YOU MAY COMMENT OUT THIS LINE 
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); 
    png_destroy_write_struct(&png_ptr, &info_ptr); 
    fclose(fp); 
    free(fname); 
} 

int main (int argc, const char * argv[]) { 
    png_uint_32 height = HEIGHT, width = WIDTH; 


    int iteration = 1; 
#ifdef REPEAT 
    for (iteration = 1; iteration <= ITERATIONS; iteration++) { 
#endif // REPEAT 

    png_bytepp imageBuffer = malloc(sizeof(png_bytep) * height); 
    for (png_uint_32 i = 0; i < height; i++) { 
     imageBuffer[i] = malloc(sizeof(png_byte) * width); 
     for (png_uint_32 j = 0; j < width; j++) { 
     imageBuffer[i][j] = 0; 
     } 
    }  

    /// CUT ACROSS THE DASHED LINES 
    /// ------------------------------------------- 
    /// NO EDITING ABOVE THIS LINE; EXCEPT AS NOTED 

    int ink = INK; 
    int x = rand() % width, y = rand() % height; 

    int xdir = (rand() % 2)?1:-1; 
    int ydir = (rand() % 2)?1:-1; 

    while (ink) { 
     imageBuffer[y][x] = 255; 
     --ink; 
     xdir += (rand() % 2)?(1):(-1); 
     ydir += (rand() % 2)?(1):(-1); 
     if (ydir > 0) { 
     ++y; 
     } else if (ydir < 0) { 
     --y; 
     } 
     if (xdir > 0) { 
     ++x; 
     } else if (xdir < 0) { 
     --x; 
     } 
     if (x == -1 || y == -1 || x == width || y == height || x == y && x == 0) { 
     x = rand() % width; y = rand() % height; 
     xdir = (rand() % 2)?1:-1; 
     ydir = (rand() % 2)?1:-1; 
     } 
    } 

    /// NO EDITING BELOW THIS LINE 
    /// ------------------------------------------- 

    writePNG(imageBuffer, width, height, iteration); 

    for (png_uint_32 i = 0; i < height; i++) { 
     free(imageBuffer[i]); 
    }  
    free(imageBuffer); 
#ifdef REPEAT 
    } 
#endif // REPEAT 
    return 0; 
} 

Nota: Si bien esta cuestión no parece estrictamente hablando "responsable" como tal; Sigo creyendo que puede dar lugar a algún tipo de respuesta "correcta". Tal vez.

Happy hunting.

Editar (de nuevo): El código fuente de los trazados Curva simplistas de mi respuesta (leer abajo) se puede encontrar here y here.

+0

+1 por una buena pregunta ;-) – ChristopheD

+0

@ChristopheD: Gracias; Pasé bastante tiempo escribiéndolo. :) –

+0

Haz que dibuje la Mona Lisa (no noté ningún requisito de "aleatoriedad". – mbeckish

Respuesta

10

Fractals? Ya no son solo para el análisis de los mercados de valores (Mandelbrot joke, lo siento).

Algunos Fractal images tienden a ser una reminiscencia de las geografías del mundo real. En particular, IFS fractales se pueden utilizar para bastante realista plants y trees, y terrain.

fractal.c es un conjunto de Mandelbrot monocromático simple, con su zoom predeterminado.


Agregado:

Context-free gramáticas pueden ser utilizados para expresar las ecuaciones que se pueden dibujar imágenes que son estéticamente agradable para los seres humanos. Jared Tarbell tiene una galería relacionada de algunas imágenes maravillosas generadas por los programas. Aza 's Algorithm Ink

segunda adición:

La otra forma principal de arte algebraica o cálculo es de Cellular automaton (CA), tales como (Juan) Conway's Game of Life, hecho famoso por la 1970 Scientific American artículo escrito por Martin Gardner. CA se re-introdujo al público con la auto-publicación de Stephen Wolfram de A New Kind of Science (NKS) en 2002.Estos tienden a ser sistemas dinámicos cerrados, que "viven" o "mueren" en base a un conjunto simple de reglas.

relacionados con fractales son chaotic systems, o sistemas dinámicos no lineales si quiere sonar inteligente. Se pueden modelar en sistemas físicos, como weather forecasting, y pueden proporcionar una salida numérica no muy aleatoria pero difícil de predecir que se puede visualizar como strange attractor (y SA).

+0

Los fractales son hermosos e interesantes, pero tal vez demasiado. En la escala de no muy alto a extremadamente interesante, caen un poco por encima de lo que tenía en mente. ;) Tienen la ventaja de ser bastante computacionalmente costosos, pero la desventaja de ser difícil de implementar. –

+0

Los fractales pueden ser realmente fáciles de implementar. Ver http://en.wikipedia.org/wiki/Sierpinski_triangle – mbeckish

+0

Escribí mis primeros programas fractales en un 68000 de 7.14 MHz usando programas cortos AmigaBASIC interpretados. Por ejemplo, la ecuación clásica de Mandelbrot es simplemente: z_ (n + 1) = (z_n)^2 + c, donde z y c son números complejos. – mctylr

2

Hmmm. Recuerdo haber hecho un generador de país en el logo hace mucho tiempo. La estrategia básica era sembrarlo con un pintor para cada color, y tener la regla: "Pintores de color, se mueven al azar, pero no pueden moverse en ninguna área que esté pintada a menos que esté pintada en su propio color". El resultado fue varias áreas pintadas contiguamente. Los pintores se movieron al azar en 4 direcciones y la cuadrícula tenía un tamaño similar a 50x50.

Una vez hecho esto, tomé mi imagen 50x50, la expandí (con el vecino más cercano) a algo mucho más grande, y usé algunos filtros gráficos estándar (desenfoque y similares) para que se vea decente. Si desea una imagen monocromática, simplemente coloque los bordes en negro y todo lo demás en blanco.

Esta estrategia no favorece en absoluto las líneas rectas.

+0

Una estrategia interesante, de hecho. Sin embargo, requiere una mucha intervención humana para obtener las imágenes más apropiadas, y lo hace, ya que estoy seguro de que bastantes de las soluciones propuestas funcionarán bien para los terrenos, pero tal vez no muchas otras cosas. –

+0

Todos los pasos que hice que implicó intervención humana cou Debería ser automatizado. Creo que casi cada vez que ejecuté el programa terminé con imágenes interesantes. Dicho esto, no cuesta mucha CPU, por lo que tal vez no sea un algoritmo ideal. – Brian

1

Esto puede haber más de un corolario de su problema que una solución a ella, pero he visto resultados interesantes de mirar a su misma idea desde un ángulo diferente:

Tome una rejilla (construirlo desde las plazas, hexágonos, o lo que sea) y generar un campo aleatorio de puntos en él. Ahora, examine todas las formas posibles de conectar ese conjunto fijo de puntos utilizando líneas que siguen la grilla. Tome fragmentos de imágenes con un tema similar (por ejemplo, hojas) y conviértelos al estilo de "línea de arte" para reducirlos a un contorno. Para cada conjunto de varios puntos, revise su biblioteca de piezas de contorno e intente encontrar una que pueda conectar los puntos (o al menos acercarse, esto puede requerir rotación, reflejo, etc.). Descubrirá que hay una gran cantidad de resultados posibles, pero si se hace correctamente, puede terminar con muchos que parecen hojas (¡incluso si son tipos de hojas "nuevos" que nunca antes se habían visto)!

+0

Ah, esto es interesante, de hecho. Pero tiene el problema fractal; va a ser muy difícil de implementar, o requerirá * mucho * de intervención humana. Todavía; una idea muy clara :) –

+0

Gracias a las imágenes de Google y a una biblioteca de procesamiento de imágenes (en Matlab, creo que fue así), pudimos crear secuencias de comandos para casi toda la generación de la biblioteca de fragmentos de imágenes. – bta

1

En lugar de la aleatoriedad directa, podría añadir un estado trivial al comportamiento. Por ejemplo, en lugar de elegir qué x y y hacer basados ​​en P donde P es esencialmente rand % 2, puede elegirlos basándose en una ecuación condicional. Como un simple ejemplo:

two-state http://img121.imageshack.us/img121/9018/twostate.png

Si permite que el estado 1 para representar 'a mantener la trayectoria de la corriente' y 0 sea 'cambio de dirección' y luego ajustando el umbral Q a controlar la frecuencia con que cambia de dirección. Agregar estados agrega complejidad, pero es probable que obtenga resultados moderadamente interesantes con valores cuidadosamente seleccionados para P y Q.

+0

Esto es similar en concepto a lo que estoy haciendo; excepto, por supuesto, que mi código no representa estados explícitos. En mi implementación, los direccionales están separados para cada eje; y tienden a convertirse en diagonales, porque tan pronto como rueden en una dirección, es poco probable que se detengan. –

+0

No es probable/poco probable en su implementación, solo hay 'rand% 2'. El uso del modelo anterior le brinda un control más estricto de la cantidad de cambio permitido en la dirección sobre un conjunto dado de puntos. La probabilidad condicional es la adición importante a su implementación actual. – ezpz

+0

Mi punto exactamente. :) (Parece que estuve un poco cansado cuando escribí el comentario.) –

0

En el espíritu de romper totalmente mis propias reglas (claramente arbitraria, he ido adelante y crearon una respuesta a mí mismo!

El código utiliza algún código muy simple curva de Bezier Tiré juntos la noche anterior, y mientras la respuesta es menos que convincente interesante, es todavía un poco de diversión. el código para los Beziers se puede encontrar here y here.

Además de editar el campo de recorte, que también añade, por supuesto,

#include "bezier.h" 

No funciona muy bien sin esta línea. ;)

/// NO EDITING ABOVE THIS LINE; EXCEPT AS NOTED 

Bezier *path = newBezier(newPoint(rand() % width,rand() % height), newPoint(rand() % width,rand() % height), newPoint(rand() % width,rand() % height), newPoint(rand() % width,rand() % height)); 

float t; 
Point *point = NULL; 

for (t = 0.0; t <= 1.0; t += 0.00000006) { 
    point = bezierPoint(path, t, point); 

    int32_t x = point->x, y = point->y; 

    if (x >= 0 && x < width && y >= 0 && y < height) 
    imageBuffer[y][x] = 255; 
} 

destroyPoint(point); 

/// NO EDITING BELOW THIS LINE 
2

La pregunta que usted está pidiendo es una estética uno. Las cosas que una persona considera "buenas" o "bellas" o "moderadamente interesantes" varían mucho de persona a persona, por lo que no creo que se pueda encontrar una mejor respuesta para esto.

Conozco a mucha gente que encontraría desagradable y sin mérito la imagen que ha publicado en su pregunta, plagada de ideas sobre la camisa de fuerza sociopolítica que es la planificación urbana. Sin embargo, I creo que se ve interesante.

+0

Si les parece "repugnante y sin mérito, plagado de ideas sobre la camisa de fuerza sociopolítica que es la planificación urbana", necesitan leer toda la publicación, ya que la imagen no tenía la intención * de verse así, es solo una interpretación de líneas y espacio. Y si eso es ** planificación ** de la ciudad; No quiero saber cómo es una ciudad * no planificada *. ;) Pero sí, la pregunta es, al menos algo, subjetiva. Pero como se mencionó, todavía creo que es fructífero, ¿no? –

+0

Además, una imagen que puede invocar tanto disgusto como interés en diferentes personas debe decirse, creo, que es * al menos * moderadamente interesante, por definición solamente. –

+0

@ Williham - Buenos comentarios sobre mi respuesta, en mi humilde opinión. Como dije en mi respuesta, me gustó. Pero mis amigos no lo hicieron. –