Hilbertify un'immagine


28

Mi piace la curva di Hilbert .


Il tuo compito per questa sfida è quello di prendere un'immagine (rigorosamente un'immagine quadrata in cui tutti i lati hanno una potenza di due pixel di larghezza) e svelarla riga per riga in modo a zig-zag e ravvivarla in una curva pseudo-Hilbert .

Unraveling

Per svelare inizierai con il pixel nell'angolo in alto a sinistra e viaggerai a destra fino ad arrivare al bordo dell'immagine. Dopo aver colpito il bordo dell'immagine, passerai alla riga successiva e inizierai a viaggiare a sinistra fino a quando non colpirai di nuovo il bordo. Continuerai a svelare riga per riga cambiando la direzione ogni volta in modo da ottenere una curva continua. Dovrebbe apparire come un gioco di serpenti ben giocato

Il risultato del dipanarsi dovrebbe essere un ordine di pixel che include ogni pixel esattamente una volta

Reraveling

Una volta che hai un ordine per i pixel, li riorganizzerai su una nuova tela di pari dimensioni seguendo il percorso di una curva pseudo-Hilbert. Per 2**nun'immagine quadrata di dimensioni dovresti usare l'ennesima iterazione della curva pseudo-hilbert. Ogni pixel verrà posizionato esattamente in un punto sulla nuova tela. Dovresti ripetere il riavvio dell'immagine in modo che il punto originariamente in alto a sinistra (l'inizio della nostra curva del serpente) rimanga lì e il punto in basso a destra (la fine della nostra curva del serpente) sia posizionato in alto a destra.

I / O

Il programma o la funzione dovrebbe includere un'immagine dei vincoli specificati tramite metodi standard e produrre un'altra immagine tramite metodi standard.

punteggio

Questo è programma di con il minor numero di byte vincenti.

Esempi

Ingresso

Mondrian

Produzione

Uscita 1


Ingresso

Rothko

Produzione

Uscita 2


Ingresso

Strapazzate

Produzione

Leone


Raccomando anche di provare su un'immagine in bianco bianca o a tinta unita per assicurarsi che non manchino pixel.

Sentiti libero di includere i tuoi risultati nelle risposte!


Va bene prendere una matrice di valori RGB anziché un'immagine come input? Che dire dell'output?
JungHwan Min

@JHM No, non puoi. Puoi scegliere il formato di immagine che desideri, quindi se la tua lingua non ha il supporto dell'immagine incorporato puoi usare un file .ppm non compresso che è molto simile a una matrice di valori RGB.
Wheat Wizard

Risposte:


8

Mathematica, 286 273 byte

Image[Array[1,{l=Length@#,l}]~ReplacePart~Thread[#&@@@Split[#&@@@FoldList[Switch[#2,"-",#{1,I},"+",#/{1,I},"F",#+{ReIm@Last@#,0},_,#]&,{{1,1},I},Characters@Nest[StringReplace@{"L"->"+RF-LFL-FR+","R"->"-LF+RFR+FL-"},"L",Log2@l]]]->Join@@MapAt[Reverse,#,2;;;;2]]]&@*ImageData

Accidenti! Impegnativo ma divertente!

Spiegazione

ImageData

Converti un Imagein una matrice di valori RGB.

Array[1,{l=Length@#,l}]

Generare un ldalla lmatrice con la testa 1, dove il lè la lunghezza dell'input (cioè la larghezza dell'immagine).

Questo produce {{1[1, 1], 1[1, 2], ..., 1[1, L]}, {1[2, 1], ..., 1[2, L]}, ..., {1[L, 1], ..., 1[L, L]}}( lscritto in maiuscolo per ridurre la confusione)

StringReplace@{"L"->"+RF-LFL-FR+","R"->"-LF+RFR+FL-"}

Una StringReplacefunzione che sostituisce ogni "L"con "+RF-LFL-FR+"e "R"con"-LF+RFR+FL-"

Nest[ ... ,"L",Log2@l]

Applicare la StringReplacefunzione per i String "L", Log2[l]i tempi.

Characters

Converti il ​​risultante Stringin a Listdi caratteri.

Switch[#2,"-",#{1,I},"+",#/{1,I},"F",#+{ReIm@Last@#,0},_,#]&

Una funzione senza nome che:

  • Se il secondo input è "-", moltiplicare il secondo elemento del primo input per I.
  • Se il secondo input è "+", dividere il secondo elemento del primo input per I.
  • Se il secondo input è "F", aumenta il primo input di ReIm(separa la parte reale e immaginaria dell'input) del secondo input.
FoldList [..., {{1,1}, I}, ...]

A partire da {{1,1},I}, applica cumulativamente la precedente funzione senza nome, usando ogni elemento Listdel carattere of come secondo input. Questo codice produce gli output di tutte le iterazioni.

#&@@@Split[#&@@@ ... ]

Sbarazzati dei secondi elementi di ciascuno Listed elimina i duplicati. (I passi fino a questo punto generano una Listdelle coordinate della curva di Hilbert)

Join@@MapAt[Reverse,#,2;;;;2]

Svela l'array RGB di input (inverte ogni altra riga e si appiattisce).

Thread[ ... -> ... ]

Crea Ruleoggetti, in modo tale che il primo elemento nel primo input (le coordinate della curva di Hilbert) sia accoppiato con il primo elemento del secondo input (l'immagine non dipinta), il secondo elemento con il secondo input e così via.

... ~ReplacePart~ ...

Applicare quelle di sostituzione Ruleal Arraydal secondo passaggio.

Image

Converti nella matrice di valori RGB in un Image.

Esempio di ingresso / uscita

Ingresso:

Caso di prova 1

Produzione:

produzione


Ingresso:

Edward e Alphonse Elric di Fullmetal Alchemist

Produzione:

wat

Funzione inversa ( 266 253 byte)

Image[MapAt[Reverse,Extract[#,#&@@@Split[#&@@@FoldList[Switch[#2,"-",#{1,I},"+",#/{1,I},"F",#+{ReIm@Last@b,0},_,#]&,{{1,1},I},Characters@Nest[StringReplace@{"L"->"+RF-LFL-FR+","R"->"-LF+RFR+FL-"},"L",Log2[l=Length@#]]]]]~Partition~l,2;;;;2]]&@*ImageData

5

Ottava 234 byte

I=imread(input(''));w=rows(I);X=[0,3;1,2];for k=2:log2(w);n=numel(X);X=[X',rot90(X',2)+3*n;X+n,X+2*n];end;for k = 1:3;I(2:2:end,:,k)=fliplr(I(2:2:end,:,k));end[~,S]=sort(X(:));I(S+(0:w^2:2*w^2))=permute(I,[2 1 3]);imwrite(I,input(''))

I nomi dei file delle immagini di input e output devono essere forniti come input standard. la dimensione del codice senza input / output è 194 byte .
Spiegazione:

Il modello di base degli indici è:

X =
  0 3
  1 2

In ogni iterazione 4 copie dal risultato della precedente iterazione effettuata e alcune trasformazioni applicate a ciascuna copia, quindi tutti i blocchi concatenati per formare il risultato corrente.

X =[0,3;1,2];
for k = 2:log2(s)
    n=numel(X);
    X = [X',rot90(X',2)+3*n;X+n,X+2*n];
end

quindi abbiamo:

block(1,1): X' 
block(1,2): rot90(X',2)+3*n 
block(2,1): X+n
block(2,2): X+2*n

0    1  | 14   15
3    2  | 13   12
--------|--------
4    7  |  8   11
5    6  |  9   10

Indici di Hilbert ordinati e indici degli elementi ordinati restituiti:

[~,S]=sort(X(:));

Svelamento applicato lanciando tutte le righe pari:

for k = 1:3
    I(2:2:end,:,k) = fliplr(I(2:2:end,:,k));
end

Ravavelling applicato:
-S ripetuto per ogni canale
-modifica applicata poiché nei dati di ottava disposti colonna saggia

I(S+(0:w^2:2*w^2))=permute(I,[2 1 3]);

Immagini di esempio:

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


Puoi scegliere di far funzionare il tuo programma come funzione se vuoi evitare di usare l'I / O.
Wheat Wizard

Le parole chiave function + end consumano più byte!
rahnema1,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.