Hilbertifikasi gambar

28

Saya suka Hilbert Curve .


Tugas Anda untuk tantangan ini adalah untuk mengambil gambar (hanya gambar persegi di mana semua sisi memiliki kekuatan dua piksel lebar) dan menguraikannya baris demi baris dengan cara zig-zagging dan putar kembali ke atas dalam kurva pseudo-Hilbert .

Terurai

Untuk mengurai Anda akan mulai dengan pixel di sudut kiri atas dan bergerak ke kanan sampai Anda tiba di tepi gambar. Setelah Anda menyentuh tepi gambar, Anda akan bergerak ke bawah ke baris berikutnya dan mulai bepergian ke kiri sampai Anda menyentuh tepi lagi. Anda akan melanjutkan mengurai baris demi baris dengan berpindah arah setiap kali sehingga Anda mendapatkan satu kurva kontinu. Ini akan terlihat seperti permainan ular yang dimainkan dengan baik

Hasil penguraian harus berupa urutan piksel yang mencakup setiap piksel tepat satu kali

Reraveling

Setelah Anda memesan piksel, Anda akan mengatur ulang piksel tersebut pada kanvas berukuran sama baru mengikuti jalur kurva pseudo-Hilbert. Untuk 2**ngambar persegi berukuran Anda harus menggunakan iterasi ke-n dari kurva pseudo-hilbert. Setiap piksel akan ditempatkan tepat di satu tempat di kanvas baru. Anda harus memutar ulang gambar sehingga titik yang semula di kiri atas (awal kurva ular kami) akan tetap ada dan titik di kanan bawah (ujung kurva ular kami) akan ditempatkan di kanan atas.

I / O

Program atau fungsi Anda harus mengambil gambar dari batasan yang ditentukan melalui metode standar dan menghasilkan gambar lain melalui metode standar.

Mencetak gol

Ini adalah program dengan kemenangan byte paling sedikit.

Contohnya

Memasukkan

Mondrian

Keluaran

Keluaran 1


Memasukkan

Rothko

Keluaran

Keluaran 2


Memasukkan

Diacak

Keluaran

Singa


Saya juga merekomendasikan pengujian pada gambar warna putih atau padat kosong untuk memastikan Anda tidak kehilangan piksel.

Jangan ragu untuk memasukkan hasil Anda sendiri dalam jawaban Anda!

Wisaya Gandum
sumber
Apakah saya tetap bisa mengambil array nilai RGB bukan sebagai gambar sebagai input? Bagaimana dengan output?
JungHwan Min
@ JKH Tidak, kamu tidak bisa. Anda dapat memilih format gambar apa pun yang Anda inginkan, jadi jika bahasa Anda tidak memiliki dukungan gambar builtin Anda dapat menggunakan file .ppm terkompresi yang sangat mirip dengan array nilai RGB.
Wheat Wizard

Jawaban:

8

Mathematica, 286 273 byte

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

Fiuh! Menantang tapi menyenangkan!

Penjelasan

ImageData

Konversikan Imagemenjadi array nilai RGB.

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

Menghasilkan loleh larray dengan kepala 1, di mana ladalah panjang input (yaitu lebar gambar).

Hasil ini {{1[1, 1], 1[1, 2], ..., 1[1, L]}, {1[2, 1], ..., 1[2, L]}, ..., {1[L, 1], ..., 1[L, L]}}( lditulis dalam huruf kapital untuk mengurangi kebingungan)

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

Sebuah StringReplacefungsi yang menggantikan setiap "L"dengan "+RF-LFL-FR+"dan "R"dengan"-LF+RFR+FL-"

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

Terapkan StringReplacefungsi ke String "L", Log2[l]kali.

Characters

Konversi hasilnya Stringmenjadi Listkarakter.

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

Fungsi tanpa nama yang:

  • Jika input kedua adalah "-", gandakan elemen kedua dari input pertama dengan I.
  • Jika input kedua adalah "+", bagi elemen kedua dari input pertama oleh I.
  • Jika input kedua adalah "F", tambah input pertama dengan ReIm(memisahkan bagian input nyata dan imajiner) dari input kedua.
Daftar Lipat [..., {{1,1}, I}, ...]

Dimulai dengan {{1,1},I}, secara kumulatif menerapkan fungsi tanpa nama di atas, menggunakan setiap elemen Listkarakter sebagai input kedua. Kode ini menghasilkan output dari semua iterasi.

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

Singkirkan elemen kedua dari masing-masing Listdan hapus duplikat. (Langkah-langkah hingga titik ini menghasilkan Listkoordinat dari kurva Hilbert)

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

Lepaskan susunan input RGB (membalikkan setiap baris dan ratakan).

Thread[ ... -> ... ]

Buat Ruleobjek, sehingga elemen pertama dalam input pertama (koordinat kurva Hilbert) dipasangkan dengan elemen pertama dari input kedua (gambar tidak terurai), elemen kedua dengan input kedua, dan seterusnya.

... ~ReplacePart~ ...

Terapkan penggantian Ruleitu ke dari Arraydari langkah kedua.

Image

Konversi ke array nilai RGB menjadi Image.

Contoh masuk / keluar

Memasukkan:

Test case 1

Keluaran:

keluaran


Memasukkan:

Edward dan Alphonse Elric dari Fullmetal Alchemist

Keluaran:

wat

Fungsi terbalik ( 266 253 byte)

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
sumber
5

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

Nama file gambar input dan output harus disediakan dari input standar. ukuran kode tanpa input / output adalah 194 byte .
Penjelasan:

Pola dasar indeks adalah:

X =
  0 3
  1 2

Dalam setiap iterasi, 4 salinan dari hasil iterasi sebelumnya dibuat dan beberapa transformasi diterapkan untuk setiap salinan kemudian semua blok disatukan untuk membentuk hasil saat ini.

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

jadi kita punya:

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

Indeks Hilbert diurutkan dan indeks elemen yang diurutkan dikembalikan:

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

Mengurai diterapkan membalik semua baris genap:

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

Reraveling diterapkan:
-S repetisi untuk setiap saluran
-permutasi diterapkan karena dalam oktaf data diatur kolom

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

Contoh gambar:

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

rahnema1
sumber
Anda dapat memilih agar program Anda berfungsi sebagai fungsi jika Anda ingin menghindari penggunaan I / O.
Wheat Wizard
fungsi + kata kunci akhir mengkonsumsi lebih banyak byte!
rahnema1