2010-03-08 9 views
22

Sommario: puoi proporre un algoritmo matematico su un piano di pixel che genererà un'immagine moderatamente interessante, preferibilmente una che nel complesso assomiglia a qualcosa?Generazione di immagini moderatamente interessanti

La storia finora:

C'era una volta ho deciso, nel tentativo di ridurre i rifiuti del ciclo sul mio (certamente troppo) numerosi computer, e di cui per generare immagini in un moderatamente interessante moda ; utilizzando un PRNG e una matematica intelligente per creare immagini che nel complesso, assomigliano a qualcosa di.

O almeno, quello era il piano. A quanto pare, la matematica intelligente richiede di essere un matematico intelligente; questo non lo sono.

A un certo punto sono arrivato a un metodo che preferiva le linee rette (dato che generalmente sono le componenti di cui è fatto il nostro mondo), forse troppo forte. Il risultato è moderatamente interessante; assomigliano, forse, le griglie della città, come ad esempio:

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

Ora per la domanda corretta: Dato il codice sorgente di questo piccolo programma; puoi migliorarlo e proporre un metodo che dia risultati un po 'più interessanti? (ad esempio non le griglie della città, ma forse le facce, gli animali, la geografia, cosa hai)

Questo è anche inteso come una sorta di sfida; Suppongo e come tale ho impostato alcune regole completamente arbitrarie e ugualmente opzionali:

  1. I commenti nel codice dicono tutto davvero. Suggerimenti e "soluzioni" dovrebbero modificare l'algoritmo stesso, non il framework circostante, eccetto per correggere gli errori che impediscono la compilazione del campione.

  2. Il codice deve essere compilato in modo pulito con un compilatore C di emissione standard. (Se l'esempio fornita non, oops! Dimmi, e io preparo. :)

  3. Il metodo dovrebbe, anche se ancora una volta, questo è facoltativo, non hanno bisogno di aiuto da suscitare tuo quartiere matematica amichevole libreria, e nel complesso utilizzare un (P) RNG come il suo canale di input dati primario .

  4. Solutions dovrebbe probabilmente essere consegnabile, semplicemente tirando fuori tutto ciò che è tra le linee snip (quelli che dicono non si deve modificare al di sopra e al di sotto, rispettivamente), con una dichiarazione per l'effetto di ciò che è necessario aggiungere in particolare al preambolo.

  5. Edit: A volte è facile dimenticare che persone su internet non possono leggere la mia mente ; ma ci vai. Il programma dovrebbe richiedere un minimo di intervento umano in la generazione delle immagini, tranne che per valutare i risultati e scegliere i migliori .

Il codice richiede un compilatore C e libpng da compilare; Non sono del tutto sicuro che il compilatore MinGW fornisca le necessità, ma sarei sorpreso se non lo facesse. Per Debian è necessario il pacchetto libpng-dev e per Mac OS X è necessario gli strumenti XCode.

Il codice sorgente può essere downloaded here.

Avviso: Codice massivo sfocatura in arrivo!

// 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: Anche se questa domanda non in senso stretto sembra "responsabili" in quanto tale; Credo ancora che possa dare origine a qualche modo di risposta "giusta". Può essere.

Buona caccia.

Edit (di nuovo): Il codice sorgente per i percorsi di Bezier semplicistici utilizzati nella mia risposta (leggi in basso) si possono trovare here e here.

+0

+1 per una bella domanda ;-) – ChristopheD

+0

@ChristopheD: Grazie; Ho passato un po 'di tempo a scriverlo. :) –

+0

Disegna la Mona Lisa (non ho notato alcun requisito di "casualità" – mbeckish

risposta

10

Fractals? Non sono più solo per l'analisi dei mercati azionari (Mandelbrot joke, scusate).

Alcuni Fractal images tendono ad essere reminiscenza delle geografie del mondo reale. In particolare, i frattali IFS possono essere utilizzati per un valore piuttosto realistico plants e trees e terrain.

fractal.c è un semplice set monocromatico di Mandelbrot, con lo zoom predefinito.


Aggiunto:

Context-free grammatiche possono essere usate per esprimere le equazioni che possono disegnare le immagini che sono esteticamente gradevoli per gli esseri umani. Jared Tarbell ha una galleria correlata di alcune meravigliose immagini generate dai programmi. Aza s' Algorithm Ink

seconda aggiunta:

L'altra forma principale dell'arte algebrico o calcolo da Cellular automaton (CA), come ad esempio (John) Conway's Game of Life, reso famoso dal 1970 Scientific American articolo scritto da Martin Gardner. CA è stata reintrodotta al pubblico con l'auto-pubblicazione di Stephen Wolfram di A New Kind of Science (NKS) nel 2002.Questi tendono ad essere sistemi dinamici chiusi, che "vivono" o "muoiono" sulla base di un semplice insieme di regole.

Relativi ai frattali sono chaotic systems o sistemi dinamici non lineari se si desidera suonare in modo intelligente. Possono essere modellati su sistemi fisici, come weather forecasting, e possono fornire output numerici non-veramente-casuali ma difficili da prevedere che possono essere visualizzati come strange attractor (e SA).

+0

I frattali sono belli e interessanti, ma forse anche troppo. Sul piano del tutto non molto interessante, cadono un po 'al di sopra di quello che avevo in mente. ;) Hanno il vantaggio di essere abbastanza computazionalmente costosi, ma lo svantaggio di essere difficili da implementare. –

+0

I frattali possono essere davvero facili da implementare. Vedi http://en.wikipedia.org/wiki/Sierpinski_triangle – mbeckish

+0

Ho scritto i miei primi programmi frattali su un 68000 a 7.14 MHz usando programmi AmigaBASIC interpretati in modo corto. Ad esempio la classica equazione di Mandelbrot è semplicemente: z_ (n + 1) = (z_n)^2 + c, dove z e c sono numeri complessi. – mctylr

2

Hmmm. Ricordo di aver creato un generatore di paese nel logo molto tempo fa. La strategia di base era quella di seminarlo con un pittore per ogni colore, e avere la regola: "I pittori di colore si muovono a caso, ma non possono spostarsi su un'area che è stata dipinta a meno che non sia dipinta nel loro colore". Il risultato sono state diverse aree dipinte in modo contiguo. I pittori si sono mossi in modo casuale in 4 direzioni e la griglia era di dimensioni pari a 50x50.

Una volta terminato, ho scattato la mia immagine 50x50, l'ho espansa (con il vicino più vicino) in qualcosa di molto più grande e ho usato alcuni filtri grafici standard (sfocatura e così via) per renderlo di aspetto decente. Se si desidera un'immagine monocromatica, basta trasformare i bordi neri e tutto il resto bianco.

Questa strategia non favorisce affatto le linee rette.

+0

Una strategia interessante, infatti. Richiede, tuttavia, un un sacco di intervento umano per creare le immagini più appropriate, e lo è, dato che sono sicuro che alcune delle soluzioni proposte funzioneranno bene per i terreni, ma forse non molte altre cose. –

+0

Tutti i passaggi che ho fatto che ha comportato un intervento umano essere automatizzato Penso che praticamente ogni volta che ho eseguito il programma mi sono ritrovato con immagini interessanti. Detto questo, non costa molto CPU, quindi forse non è un algoritmo ideale. – Brian

1

questo può essere più di un corollario al vostro problema che una soluzione ad essa, ma ho visto risultati interessanti dal guardando il tuo stesso concetto da una diversa angolazione:

Prendere una griglia (costruire da piazze, esagoni, o cosa hai) e genera un campo casuale di punti su di esso. Ora, esamina tutti i modi possibili per collegare quel set fisso di punti usando le linee che seguono la griglia. Prendi frammenti di immagini con un tema simile (ad esempio, foglie) e convertili in stile "line art" per ridurli a un contorno. Per ogni serie di punti diversi, guarda attraverso la tua libreria di elementi di contorno e prova a trovarne uno che possa collegare i punti (o quanto meno avvicinarsi, potrebbe richiedere rotazione, mirroring, ecc.). Scoprirai che ci sono una miriade di possibili risultati, ma se fatti correttamente potresti ritrovarti con molti che sembrano foglie (anche se sono "nuovi" tipi di foglie che non sono mai stati visti prima)!

+0

Ah, questo è interessante, davvero. Ma ha il problema frattale; sarà piuttosto difficile da implementare, o richiedere un * lotto * di intervento umano. Ancora; un'idea molto carina :) –

+0

Grazie alle immagini di Google e una libreria di elaborazione delle immagini (in Matlab, penso che lo fosse), siamo stati in grado di scrivere quasi tutta la generazione della libreria dei frammenti di immagine. – bta

1

Al posto di una casualità casuale, è possibile aggiungere alcuni aspetti banali al comportamento. Ad esempio, invece di scegliere cosa fare x e in base a P dove P è essenzialmente rand % 2, è possibile selezionarli in base a un'equazione condizionale. Come semplice esempio:

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

Se si consente stato 1 rappresentare 'mantenere percorso di corrente' e 0 essere 'cambiare direzione' quindi regolando la soglia Q controllare la frequenza con cui si cambia direzione. Aggiungere stati aggiunge complessità, ma probabilmente otterrai risultati moderatamente interessanti con valori scelti con cura per P e Q.

+0

Questo concetto è simile a quello che sto facendo; tranne, ovviamente, che il mio codice non rappresenta stati espliciti. Nella mia implementazione, le direzionali sono separate per ciascun asse; e tendono a trasformarsi in diagonali, perché non appena si muovono in una direzione, è improbabile che si fermino. –

+0

Non c'è probabilmente/improbabile nella vostra implementazione, c'è solo 'rand% 2'. L'uso del modello sopra ti dà un controllo più stretto di quanto è permesso un cambio di direzione su un determinato set di punti. La probabilità condizionata è l'aggiunta importante all'attuale implementazione. – ezpz

+0

Il mio punto esattamente. :) (Mi sembra di essere stato un po 'stanco quando ho scritto il commento.) –

0

Nello spirito del tutto sconvolgente mie (le regole per ammissione arbitrarie, sono andato avanti a destra e ha creato una risposta me stesso!

Il codice utilizza alcuni molto semplice codice curva di Bezier ho buttato insieme la scorsa notte, e mentre la risposta è meno che irresistibilmente interessante, è ancora un po 'divertente. il codice per le beziers può essere trovato here e here.

Oltre a modificare il campo snip, ho anche aggiunto, naturalmente,

#include "bezier.h" 

Non funziona molto bene senza questa linea. ;)

/// 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 questione si sta chiedendo è un estetica uno. Le cose che una persona considera "buone" o "belle" o "moderatamente interessanti" variano così ampiamente da persona a persona che non penso che una risposta migliore possa essere trovata.

Conosco molte persone che potrebbero trovare l'immagine che hai pubblicato nella tua domanda di essere disgustosa e senza merito, crivellata dalle idee della camicia di forza socio-politica che è la pianificazione urbana. Tuttavia, I penso che sia interessante.

+0

Se lo trovano "disgustoso e senza merito, crivellato dalle idee della camicia di forza socio-politica che è urbanistica", hanno bisogno di leggere l'intero post, in quanto l'immagine non era in realtà * destinata * ad apparire come tale, è solo un'interpretazione di linee e spazio. E se quella è città ** pianificazione **; Non voglio sapere come appare una città * non pianificata *. ;) Ma sì, la domanda è, almeno in qualche modo, soggettiva. Ma come detto, continuo a pensare che sia fruttuoso, no? –

+0

Inoltre, un'immagine che è in grado di invocare sia il disgusto che l'interesse in persone diverse deve essere detta, ritengo, per essere * almeno * moderatamente interessante, solo per definizione. –

+0

@ Williham - Buoni commenti sulla mia risposta, IMHO. Come ho detto nella mia risposta, mi è piaciuto. Ma i miei amici no. –

Problemi correlati