Hilbertificar una imagen

28

Me gusta la curva de Hilbert .


Su tarea para este desafío es tomar una imagen (estrictamente una imagen cuadrada donde todos los lados tienen una potencia de dos píxeles de ancho) y desentrañarla línea por línea en forma de zigzagueo y descifrarla en una curva pseudo-Hilbert .

Desentrañar

Para desentrañar, comenzará con el píxel en la esquina superior izquierda y viajará a la derecha hasta llegar al borde de la imagen. Una vez que haya alcanzado el borde de la imagen, se moverá hacia la siguiente fila y comenzará a viajar hacia la izquierda hasta que vuelva a tocar el borde. Continuará desentrañando fila por fila cambiando la dirección cada vez para obtener una curva continua. Esto debería verse como un juego de serpientes bien jugado

El resultado de desentrañar debería ser un orden de píxeles que incluye cada píxel exactamente una vez

Replanteando

Una vez que haya ordenado los píxeles, los reorganizará en un nuevo lienzo de igual tamaño siguiendo el camino de una curva pseudo-Hilbert. Para una 2**nimagen cuadrada de tamaño, debe usar la enésima iteración de la curva pseudo-hilbert. Cada píxel se colocará exactamente en un punto en el nuevo lienzo. Debe volver a dibujar la imagen para que el punto originalmente en la parte superior izquierda (el comienzo de nuestra curva de serpiente) permanezca allí y el punto en la parte inferior derecha (el final de nuestra curva de serpiente) se coloque en la parte superior derecha.

I / O

Su programa o función debe tomar una imagen de restricciones especificadas a través de métodos estándar y generar otra imagen a través de métodos estándar.

Tanteo

Este es programa de con la menor cantidad de bytes ganados.

Ejemplos

Entrada

Mondrian

Salida

Salida 1


Entrada

Rothko

Salida

Salida 2


Entrada

Revuelto

Salida

León


También recomiendo probar en una imagen en blanco o en color sólido para asegurarse de que no le faltan píxeles.

¡No dude en incluir sus propios resultados en sus respuestas!

Asistente de trigo
fuente
¿Está bien tomar una matriz de valores RGB en lugar de una imagen como entrada? ¿Qué pasa con la salida?
JungHwan Min
@JHM No, no puedes. Sin embargo, puede elegir el formato de imagen que desee, por lo que si su idioma no es compatible con imágenes incorporadas, puede usar un archivo .ppm sin comprimir que es muy similar a una matriz de valores RGB.
Wheat Wizard

Respuestas:

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

¡Uf! ¡Desafiante pero divertido!

Explicación

ImageData

Convierta una Imageen una matriz de valores RGB.

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

Genere una matriz lby lcon head 1, donde les la longitud de la entrada (es decir, el ancho de la imagen).

Esto produce {{1[1, 1], 1[1, 2], ..., 1[1, L]}, {1[2, 1], ..., 1[2, L]}, ..., {1[L, 1], ..., 1[L, L]}}( lescrito en mayúsculas para reducir la confusión)

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

Una StringReplacefunción que reemplaza cada "L"con "+RF-LFL-FR+"y "R"con"-LF+RFR+FL-"

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

Aplicar la StringReplacefunción de los String "L", Log2[l]tiempos.

Characters

Convierta el resultado Stringen una Listde caracteres.

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

Una función sin nombre que:

  • Si la segunda entrada es "-", multiplique el segundo elemento de la primera entrada por I.
  • Si la segunda entrada es "+", divida el segundo elemento de la primera entrada por I.
  • Si la segunda entrada es "F", aumente la primera entrada por ReIm(separa la parte real e imaginaria de la entrada) de la segunda entrada.
Lista de plegado [..., {{1,1}, I}, ...]

Comenzando con {{1,1},I}, aplique de forma acumulativa la función sin nombre anterior, utilizando cada elemento de los Listcaracteres como segunda entrada. Este código produce los resultados de todas las iteraciones.

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

Deshágase de los segundos elementos de cada uno Listy elimine los duplicados. (Los pasos hasta este punto generan una Listde las coordenadas de la curva de Hilbert)

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

Desentrañar la matriz RGB de entrada (invierte cada dos filas y se aplana).

Thread[ ... -> ... ]

Cree Ruleobjetos, de modo que el primer elemento en la primera entrada (las coordenadas de la curva de Hilbert) se empareje con el primer elemento de la segunda entrada (la imagen desenredada), el segundo elemento con la segunda entrada, y así sucesivamente.

... ~ReplacePart~ ...

Aplique esos reemplazos Ruleal Arraydel segundo paso.

Image

Convierte a la matriz de valores RGB en un Image.

Muestra de entrada / salida

Entrada:

Caso de prueba 1

Salida:

salida


Entrada:

Edward y Alphonse Elric de Fullmetal Alchemist

Salida:

wat

Función inversa ( 266253 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
fuente
5

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

Los nombres de archivo de las imágenes de entrada y salida deben proporcionarse a partir de la entrada estándar. El tamaño del código sin entrada / salida es de 194 bytes .
Explicación:

El patrón base de los índices es:

X =
  0 3
  1 2

En cada iteración, 4 copias del resultado de la iteración anterior realizada y alguna transformación aplicada a cada copia, luego todos los bloques se concatenan para formar el resultado actual.

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

entonces tenemos:

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

Índices de Hilbert ordenados e índices de elementos ordenados devueltos:

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

Desentrañar aplicado volteando todas las filas pares:

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

Replanteo aplicado:
-S repetido para cada canal
-permutación aplicada ya que en los datos de octava dispuestos en columnas

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

Imágenes de ejemplo:

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

rahnema1
fuente
Puede elegir que su programa funcione como una función si desea evitar el uso de E / S.
Wheat Wizard
La función + palabras clave finales consume más bytes!
rahnema1