Hilbertify ein Bild

28

Ich mag die Hilbert-Kurve .


Ihre Aufgabe für diese Herausforderung ist es, ein Bild (ausschließlich ein quadratisches Bild, bei dem alle Seiten eine Stärke von zwei Pixeln haben) aufzunehmen, zickzackförmig zeilenweise zu entwirren und es in einer Pseudo-Hilbert-Kurve wieder aufzurollen .

Auflösen

Zum Auflösen beginnen Sie mit dem Pixel in der oberen linken Ecke und bewegen sich nach rechts, bis Sie am Bildrand ankommen. Sobald Sie den Bildrand erreicht haben, springen Sie in die nächste Reihe und bewegen sich nach links, bis Sie den Bildrand erneut erreichen. Sie werden fortfahren, Reihe für Reihe zu entwirren, indem Sie die Richtung jedes Mal wechseln, so dass Sie eine kontinuierliche Kurve erhalten. Dies sollte wie ein gut gespieltes Schlangenspiel aussehen

Das Ergebnis des Auflösens sollte eine Pixelreihenfolge sein, die jedes Pixel genau einmal enthält

Umschiffen

Sobald Sie eine Reihenfolge für die Pixel festgelegt haben, ordnen Sie sie auf einer neuen Leinwand gleicher Größe neu an, die dem Pfad einer Pseudo-Hilbert-Kurve folgt. Für ein 2**nquadratisches Bild sollten Sie die n-te Iteration der Pseudohilbert-Kurve verwenden. Jedes Pixel wird genau an einer Stelle auf der neuen Leinwand platziert. Sie sollten das Bild neu berechnen, sodass der Punkt oben links (der Anfang unserer Schlangenkurve) dort bleibt und der Punkt unten rechts (das Ende unserer Schlangenkurve) oben rechts platziert wird.

I / O

Ihr Programm oder Ihre Funktion sollte ein Abbild bestimmter Einschränkungen über Standardmethoden aufnehmen und ein anderes Abbild über Standardmethoden ausgeben.

Wertung

Dies ist ein Programm mit den wenigsten Gewinnen.

Beispiele

Eingang

Mondrian

Ausgabe

Ausgang 1


Eingang

Rothko

Ausgabe

Ausgang 2


Eingang

Durcheinander gebracht

Ausgabe

Löwe


Ich empfehle auch, ein leeres weißes oder einfarbiges Bild zu testen, um sicherzustellen, dass keine Pixel fehlen.

Fühlen Sie sich frei, Ihre eigenen Ergebnisse in Ihre Antworten einzubeziehen!

Weizen-Assistent
quelle
Ist es in Ordnung, ein Array von RGB-Werten anstelle eines Bildes als Eingabe zu verwenden? Was ist mit der Ausgabe?
JungHwan Min
@ JHM Nein, kannst du nicht. Sie können jedoch jedes gewünschte Bildformat auswählen. Wenn Ihre Sprache keine integrierte Bildunterstützung bietet, können Sie eine nicht komprimierte PPM-Datei verwenden, die einem Array von RGB-Werten sehr ähnlich ist.
Wheat Wizard

Antworten:

8

Mathematica, 286 273 Bytes

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

Puh! Anspruchsvoll aber spaßig!

Erläuterung

ImageData

Konvertieren Sie ein Imagein ein Array von RGB-Werten.

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

Generieren eines lvon lArray mit Kopf 1, wobei die ldie Länge des Eingangssignals (dh , die Breite des Bildes).

Dies ergibt {{1[1, 1], 1[1, 2], ..., 1[1, L]}, {1[2, 1], ..., 1[2, L]}, ..., {1[L, 1], ..., 1[L, L]}}( lin Großbuchstaben geschrieben, um Verwirrung zu vermeiden)

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

Eine StringReplaceFunktion, die jedes "L"mit "+RF-LFL-FR+"und "R"mit ersetzt"-LF+RFR+FL-"

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

Tragen Sie die StringReplaceFunktion auf die String "L", Log2[l]mal.

Characters

Konvertieren Sie das Ergebnis Stringin ein Listvon Zeichen.

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

Eine unbenannte Funktion, die:

  • Wenn die zweite Eingabe ist "-", multiplizieren Sie das zweite Element der ersten Eingabe mit I.
  • Wenn die zweite Eingabe ist "+", dividieren Sie das zweite Element der ersten Eingabe durch I.
  • Wenn die zweite Eingabe ist "F", erhöhen Sie die erste Eingabe um den ReIm(trennt den Real- und Imaginärteil der Eingabe) der zweiten Eingabe.
FoldList [..., {{1,1}, I}, ...]

Wenden Sie beginnend mit {{1,1},I}die oben genannte unbenannte Funktion kumulativ an und verwenden Sie dabei jedes Element Listder Zeichen als zweite Eingabe. Dieser Code liefert die Ausgaben aller Iterationen.

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

Beseitigen Sie die zweiten Elemente Listund löschen Sie Duplikate. (Die Schritte bis zu diesem Punkt erzeugen eine Anzahl Listvon Koordinaten der Hilbert-Kurve.)

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

Entwirre das Eingabe-RGB-Array (kehrt jede zweite Zeile um und flacht ab).

Thread[ ... -> ... ]

Erstellen Sie RuleObjekte, sodass das erste Element in der ersten Eingabe (die Koordinaten der Hilbert-Kurve) mit dem ersten Element der zweiten Eingabe (dem enträtselten Bild), dem zweiten Element mit der zweiten Eingabe usw. gepaart wird.

... ~ReplacePart~ ...

Wenden Sie diese Ersetzungen Ruleauf Arrayden zweiten Schritt an.

Image

Konvertieren Sie in das Array von RGB-Werten in ein Image.

Probe ein / aus

Eingang:

Testfall 1

Ausgabe:

Ausgabe


Eingang:

Edward und Alphonse Elric vom Fullmetal Alchemist

Ausgabe:

wat

Inverse Funktion ( 266 253 Bytes)

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
JungHwan min
quelle
5

Oktave 234 Bytes

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(''))

Dateinamen von Eingabe- und Ausgabebildern sollten als Standardeingabe bereitgestellt werden. Die Größe des Codes ohne Eingabe / Ausgabe beträgt 194 Bytes .
Erläuterung:

Das Grundmuster von Indizes ist:

X =
  0 3
  1 2

In jeder Iteration werden 4 Kopien des Ergebnisses der vorherigen Iteration erstellt und eine Transformation auf jede Kopie angewendet. Anschließend werden alle Blöcke verkettet, um das aktuelle Ergebnis zu bilden.

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

also haben wir:

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

Hilbert-Indizes sortiert und Indizes der sortierten Elemente zurückgegeben:

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

Auflösen angewendet alle geraden Reihen spiegeln:

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

Reraveling angewendet: -
Wiederholt für jeden Kanal. -
Permutation angewendet, da die Oktavdaten spaltenweise angeordnet sind

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

Beispielbilder:

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

rahnema1
quelle
Sie können festlegen, dass Ihr Programm als Funktion ausgeführt wird, wenn Sie die Verwendung von E / A vermeiden möchten.
Weizen-Assistent
Die Schlüsselwörter function + end belegen mehr Bytes!
rahnema1