Hilbertify изображение

28

Мне нравится кривая Гильберта .


Ваша задача для этой задачи состоит в том, чтобы взять изображение (строго квадратное изображение, где все стороны имеют степень ширины в два пикселя), расправить его построчно зигзагообразно и растянуть его обратно по псевдогильбертовой кривой. ,

Unraveling

Чтобы распутать, вы начнете с пикселя в верхнем левом углу и двигаетесь вправо, пока не дойдете до края изображения. Как только вы дойдете до края изображения, вы переместитесь вниз к следующему ряду и начнете движение влево, пока не дойдете до края снова. Вы будете продолжать распутывать строки за строкой, переключая направление каждый раз, чтобы получить одну непрерывную кривую. Это должно выглядеть как хорошо играемая игра змеи

Результат распутывания должен быть порядка пикселей, который включает каждый пиксель ровно один раз

Reraveling

Как только у вас будет порядок для пикселей, вы переставите их на новом холсте одинакового размера, следуя пути псевдогильбертовой кривой. Для изображения 2**nквадратного размера вы должны использовать n-ю итерацию псевдогильбертовой кривой. Каждый пиксель будет размещен ровно в одном месте на новом холсте. Вы должны перерисовать изображение так, чтобы точка, изначально находящаяся в верхнем левом углу (начало нашей кривой змей), оставалась там, а точка в правом нижнем углу (конец нашей кривой змей) была помещена в верхнем правом углу.

I / O

Ваша программа или функция должны получать изображение с указанными ограничениями стандартными методами и выводить другое изображение стандартными методами.

счет

Это программа с минимальным количеством байтов.

Примеры

вход

Mondrian

Выход

Выход 1


вход

Ротко

Выход

Выход 2


вход

Яичница

Выход

лев


Я также рекомендую провести тестирование на чистом белом или сплошном цветном изображении, чтобы убедиться, что вы не пропустили ни одного пикселя.

Не стесняйтесь включать свои собственные результаты в свои ответы!

Мастер пшеницы
источник
Можно ли использовать массив значений RGB вместо изображения в качестве входных данных? Как насчет вывода?
JungHwan Мин
@JHM Нет, ты не можешь. Вы можете выбрать любой формат изображения, который хотите, поэтому, если ваш язык не имеет встроенной поддержки изображений, вы можете использовать несжатый файл .ppm, который очень похож на массив значений RGB.
Wheat Wizard

Ответы:

8

Mathematica, 286 273 байта

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

Уф! Сложно, но весело!

объяснение

ImageData

Преобразовать Imageв массив значений RGB.

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

Генерирует с lпомощью lмассива с головой 1, где lесть длина входного сигнала (т.е. ширины изображения).

Это дает {{1[1, 1], 1[1, 2], ..., 1[1, L]}, {1[2, 1], ..., 1[2, L]}, ..., {1[L, 1], ..., 1[L, L]}}( lнаписано заглавными буквами, чтобы уменьшить путаницу)

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

StringReplaceФункция , которая заменяет каждый "L"с "+RF-LFL-FR+"и "R"с"-LF+RFR+FL-"

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

Примените StringReplaceфункцию к String "L", Log2[l]раз.

Characters

Преобразование Результирующего Stringв Listперсонажах.

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

Безымянная функция, которая:

  • Если второй вход - "-"умножьте второй элемент первого входа на I.
  • Если второй вход есть "+", разделите второй элемент первого входа на I.
  • Если второй вход есть "F", увеличьте первый вход на ReIm(отделяет действительную и мнимую часть входа) от второго входа.
FoldList [..., {{1,1}, I}, ...]

Начиная с {{1,1},I}кумулятивного применения вышеуказанной безымянной функции, используя каждый элемент Listсимволов в качестве второго ввода. Этот код выдает результаты всех итераций.

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

Избавьтесь от вторых элементов каждого Listи удалите дубликаты. (Шаги до этой точки генерируют Listкоординаты кривой Гильберта)

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

Распутайте входной массив RGB (переворачивает каждую вторую строку и выравнивает).

Thread[ ... -> ... ]

Создайте Ruleобъекты так, чтобы первый элемент в первом входе (координаты кривой Гильберта) был связан с первым элементом второго входа (развернутым изображением), вторым элементом со вторым входом и так далее.

... ~ReplacePart~ ...

Примените эти замены Ruleдля Arrayвторого этапа.

Image

Преобразовать в массив значений RGB в Image.

Образец в / из

Входные данные:

Тестовый пример 1

Выход:

выход


Входные данные:

Эдвард и Альфонс Элрик из Стального Алхимика

Выход:

Wat

Обратная функция ( 266 253 байта)

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

Октава 234 байта

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

Имена файлов входных и выходных изображений должны предоставляться из стандартного ввода. размер кода без ввода / вывода составляет 194 байта .
Объяснение:

Базовая структура индексов:

X =
  0 3
  1 2

В каждой итерации 4 копии из результата предыдущей итерации и некоторое преобразование, применяемое к каждой копии, затем все блоки объединяются для формирования текущего результата.

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

итак имеем:

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

Сортировка индексов Гильберта и возвращение индексов отсортированных элементов:

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

Распутывание применяется переворачиванием всех четных строк:

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

Применяется перераспределение:
-S повторяется для каждого канала
-Перестановка применяется, так как в данных октавы расположены по столбцам

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

Примеры изображений:

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

rahnema1
источник
Вы можете выбрать, чтобы ваша программа работала как функция, если вы хотите избежать ввода-вывода.
Пшеничный Волшебник
ключевые слова function + end потребляют больше байтов!
rahnema1