Hilbertifier une image

28

J'aime la courbe de Hilbert .


Votre tâche pour ce défi est de prendre une image (strictement une image carrée où tous les côtés ont une puissance de deux pixels de large) et de la démêler ligne par ligne en zigzaguant et de la défiler en arrière dans une courbe pseudo-Hilbert .

Démêler

Pour démêler, vous commencerez avec le pixel dans le coin supérieur gauche et voyagerez à droite jusqu'à ce que vous arriviez au bord de l'image. Une fois que vous avez touché le bord de l'image, vous descendez à la ligne suivante et commencez à voyager à gauche jusqu'à ce que vous frappiez à nouveau le bord. Vous continuerez à démêler ligne par ligne en changeant de direction à chaque fois afin d'obtenir une courbe continue. Cela devrait ressembler à un jeu de serpent bien joué

Le résultat du démêlage doit être un ordre de pixels qui inclut chaque pixel exactement une fois

Reraveling

Une fois que vous aurez commandé les pixels, vous les réorganiserez sur un nouveau canevas de taille égale suivant le chemin d'une pseudo-courbe de Hilbert. Pour une 2**nimage carrée de taille, vous devez utiliser la nième itération de la courbe pseudo-hilbert. Chaque pixel sera placé exactement à un endroit sur la nouvelle toile. Vous devez redéfinir l'image afin que le point initialement en haut à gauche (le début de notre courbe de serpent) y reste et que le point en bas à droite (la fin de notre courbe de serpent) soit placé en haut à droite.

E / S

Votre programme ou fonction doit prendre une image des contraintes spécifiées via des méthodes standard et produire une autre image via des méthodes standard.

Notation

Il s'agit d' programme de avec le moins de victoires d'octets.

Exemples

Contribution

Mondrian

Sortie

Sortie 1


Contribution

Rothko

Sortie

Sortie 2


Contribution

Brouillé

Sortie

Lion


Je recommande également de tester sur une image vierge en blanc ou en couleur unie pour vous assurer qu'il ne manque aucun pixel.

N'hésitez pas à inclure vos propres résultats dans vos réponses!

Assistant de blé
la source
Est-il correct de prendre un tableau de valeurs RVB au lieu d'une image comme entrée? Et la sortie?
JungHwan Min
@JHM Non, vous ne pouvez pas. Vous pouvez cependant choisir le format d'image que vous souhaitez, donc si votre langue ne prend pas en charge l'image intégrée, vous pouvez utiliser un fichier .ppm non compressé qui est très similaire à un tableau de valeurs RVB.
Wheat Wizard

Réponses:

8

Mathematica, 286 273 octets

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

Phew! Difficile mais amusant!

Explication

ImageData

Convertissez un Imageen un tableau de valeurs RVB.

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

Générez un tableau lpar lavec tête 1, où lest la longueur de l'entrée (c'est-à-dire la largeur de l'image).

Cela donne {{1[1, 1], 1[1, 2], ..., 1[1, L]}, {1[2, 1], ..., 1[2, L]}, ..., {1[L, 1], ..., 1[L, L]}}( lécrit en majuscules pour réduire la confusion)

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

Une StringReplacefonction qui remplace tout "L"avec "+RF-LFL-FR+"et "R"avec"-LF+RFR+FL-"

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

Appliquer la StringReplacefonction aux String "L", les Log2[l]temps.

Characters

Convertissez le résultat Stringen un Listde caractères.

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

Une fonction sans nom qui:

  • Si la deuxième entrée est "-", multipliez le deuxième élément de la première entrée par I.
  • Si la deuxième entrée est "+", divisez le deuxième élément de la première entrée par I.
  • Si la deuxième entrée est "F", augmentez la première entrée de ReIm(sépare la partie réelle et imaginaire de l'entrée) de la deuxième entrée.
FoldList [..., {{1,1}, I}, ...]

En commençant par {{1,1},I}, appliquer cumulativement la fonction sans nom ci-dessus, en utilisant chaque élément Listdes caractères comme deuxième entrée. Ce code produit les sorties de toutes les itérations.

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

Débarrassez-vous des seconds éléments de chacun Listet supprimez les doublons. (Les étapes jusqu'à ce point génèrent une Listdes coordonnées de la courbe de Hilbert)

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

Démêlez le tableau RVB d'entrée (inverse toutes les autres lignes et s'aplatit).

Thread[ ... -> ... ]

Créez des Ruleobjets, de telle sorte que le premier élément de la première entrée (les coordonnées de la courbe de Hilbert) soit associé au premier élément de la deuxième entrée (l'image démêlée), le deuxième élément avec la deuxième entrée, etc.

... ~ReplacePart~ ...

Appliquez ces remplacements Ruleà Arraypartir de la deuxième étape.

Image

Convertir en tableau de valeurs RVB en un Image.

Échantillon entrant / sortant

Contribution:

Cas de test 1

Sortie:

sortie


Contribution:

Edward et Alphonse Elric de Fullmetal Alchemist

Sortie:

wat

Fonction inverse ( 266 253 octets)

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
la source
5

Octave 234 octets

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

Les noms de fichier des images d'entrée et de sortie doivent être fournis sous forme d'entrée standard. la taille du code sans entrée / sortie est de 194 octets .
Explication:

Le modèle de base des indices est le suivant:

X =
  0 3
  1 2

Dans chaque itération, 4 copies du résultat de l'itération précédente effectuée et une transformation appliquée à chaque copie, puis tous les blocs concaténés pour former le résultat actuel.

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

nous avons donc:

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

Index de Hilbert triés et index des éléments triés renvoyés:

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

Démêlage appliqué en retournant toutes les lignes paires:

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

Ré-ondulation appliquée:
-S répété pour chaque canal-
permutation appliquée car en octave les données sont disposées en colonnes

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

Exemples d'images:

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

rahnema1
la source
Vous pouvez choisir de faire fonctionner votre programme en tant que fonction si vous souhaitez éviter d'utiliser les E / S.
Wheat Wizard
Les mots-clés function + end consomment plus d'octets!
rahnema1