Hilbertify obrazu


28

Lubię krzywą Hilberta .


Twoim zadaniem w tym wyzwaniu jest zrobienie zdjęcia (dokładnie kwadratowego obrazu, którego wszystkie boki mają moc dwóch pikseli szerokości) i rozplątanie go linia po linii w zygzakowaty sposób i wbicie go z powrotem w pseudo-krzywą Hilberta .

Rozplątywanie

Aby rozwikłać, zacznij od piksela w lewym górnym rogu i podróżuj w prawo, aż dojdziesz do krawędzi obrazu. Po uderzeniu w krawędź obrazu przejdziesz do następnego rzędu i zaczniesz jechać w lewo, aż ponownie dotkniesz krawędzi. Będziesz kontynuował rozplątywanie rząd po rzędzie za każdym razem zmieniając kierunek, aby uzyskać jedną ciągłą krzywą. Powinno to wyglądać jak dobrze zagrana gra w węża

Wynikiem rozwikłania powinna być kolejność pikseli, która obejmuje każdy piksel dokładnie raz

Reraveling

Po otrzymaniu zamówienia na piksele przestawisz je na nowe płótno o równej wielkości, podążając ścieżką pseudo-krzywej Hilberta. W przypadku 2**nkwadratowego obrazu o wielkości należy użyć n-tej iteracji krzywej pseudo-Hilberta. Każdy piksel zostanie umieszczony w dokładnie jednym miejscu na nowym płótnie. Powinieneś odwrócić obraz, aby punkt pierwotnie w lewym górnym rogu (początek naszej krzywej węża) pozostał tam i punkt w prawym dolnym rogu (koniec naszej krzywej węża) został umieszczony w prawym górnym rogu.

I / O

Twój program lub funkcja powinna pobrać obraz określonych ograniczeń standardowymi metodami i wygenerować inny obraz standardowymi metodami.

Punktacja

Jest to program do z najmniejszą liczbą bajtów wygranych.

Przykłady

Wkład

Mondrian

Wydajność

Wyjście 1


Wkład

Rothko

Wydajność

Wyjście 2


Wkład

Jajecznica

Wydajność

Lew


Polecam również testowanie na pustym białym lub jednolitym kolorze obrazu, aby upewnić się, że nie brakuje żadnych pikseli.

Dołącz swoje wyniki do swoich odpowiedzi!


Czy można wprowadzać tablicę wartości RGB zamiast obrazu jako danych wejściowych? Co z wydajnością?
JungHwan Min

@JHM Nie, nie możesz. Możesz jednak wybrać dowolny format obrazu, więc jeśli twój język nie ma wbudowanej obsługi obrazu, możesz użyć nieskompresowanego pliku .ppm, który jest bardzo podobny do tablicy wartości RGB.
Kreator pszenicy,

Odpowiedzi:


8

Mathematica, 286 273 bajtów

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

Uff! Trudne, ale zabawne!

Wyjaśnienie

ImageData

Konwertuj an Imagena tablicę wartości RGB.

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

Wygenerowania lprzez ltablicę z głowicy 1, w której ljest długością wejścia (tj szerokość obrazu).

Daje to {{1[1, 1], 1[1, 2], ..., 1[1, L]}, {1[2, 1], ..., 1[2, L]}, ..., {1[L, 1], ..., 1[L, L]}}( lzapisane wielkimi literami, aby zmniejszyć zamieszanie)

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

StringReplaceFunkcja, która zastępuje każdy "L"z "+RF-LFL-FR+"oraz "R"z"-LF+RFR+FL-"

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

Zastosuj StringReplacefunkcję do String "L", Log2[l]razy.

Characters

Przekształć wynik Stringw postaci Listznaków.

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

Nienazwana funkcja, która:

  • Jeśli drugim wejściem jest "-", pomnóż drugi element pierwszego wejścia przez I.
  • Jeśli drugim wejściem jest "+", podziel drugi element pierwszego wejścia przez I.
  • Jeśli drugim wejściem jest "F", zwiększ pierwsze wejście o ReIm(oddziela rzeczywistą i urojoną część wejścia) drugiego wejścia.
FoldList [..., {{1,1}, I}, ...]

Zaczynając od {{1,1},I}, zastosuj łącznie powyższą nienazwaną funkcję, używając każdego elementu Listznaków jako drugiego wejścia. Ten kod zwraca wyniki wszystkich iteracji.

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

Pozbądź się drugich elementów każdego z nich Listi usuń duplikaty. (Kroki do tego punktu generują Listwspółrzędne krzywej Hilberta)

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

Rozwiń wejściową tablicę RGB (odwraca co drugi rząd i spłaszcza).

Thread[ ... -> ... ]

Utwórz Ruleobiekty, tak aby pierwszy element na pierwszym wejściu (współrzędne krzywej Hilberta) został sparowany z pierwszym elementem na drugim wejściu (rozpleciony obraz), drugim elementem z drugim wejściem i tak dalej.

... ~ReplacePart~ ...

Stosować te zamienne Ruledo danego Arrayz drugiego etapu.

Image

Konwertuj na tablicę wartości RGB na an Image.

Próbkuj wejście / wyjście

Wkład:

Przypadek testowy 1

Wydajność:

wydajność


Wkład:

Edward i Alphonse Elric z Fullmetal Alchemist

Wydajność:

wat

Funkcja odwrotna ( 266 253 bajtów)

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

Oktawa 234 bajtów

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

Nazwy plików obrazów wejściowych i wyjściowych należy podać ze standardowego wejścia. rozmiar kodu bez wejścia / wyjścia wynosi 194 bajty .
Wyjaśnienie:

Podstawowym wzorem indeksów jest:

X =
  0 3
  1 2

W każdej iteracji 4 kopie z wyniku poprzedniej wykonanej iteracji i niektóre transformacje zastosowane do każdej kopii, a następnie wszystkie bloki połączone w celu utworzenia bieżącego wyniku.

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

więc mamy:

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

Posortowane indeksy Hilberta i zwrócone indeksy posortowanych elementów:

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

Rozplątywanie zastosowano odwracanie wszystkich parzystych wierszy:

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

Zastosowano ponowne znakowanie:
-S powtórzone dla każdego kanału
-permutacja zastosowana, ponieważ w danych Octave ułożono kolumnę

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

Przykładowe obrazy:

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj


Możesz wybrać, aby twój program działał jako funkcja, jeśli chcesz uniknąć używania I / O.
Kreator pszenicy,

słowa kluczowe function + end zużywają więcej bajtów!
rahnema1
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.