画像のヒルベルト化


28

私はヒルベルト曲線が好きです。


この課題のタスクは、画像(すべての辺が2ピクセルの幅である厳密に正方形の画像)を取得し、ジグザグ形式で1行ずつ展開し、擬似ヒルベルト曲線で元に戻すことです。 。

解き明かす

解くには、左上隅のピクセルから始めて、画像の端に到達するまで右に進みます。画像の端に到達したら、次の行に移動し、再び端に到達するまで左に移動し始めます。行を切り替えるたびに行を解き続けて、1つの連続した曲線を取得します。これはヘビのよくプレイされるゲームのように見えるはずです

展開の結果は、すべてのピクセルを1回だけ含むピクセルの順序になります。

レラベリング

ピクセルの順序が決まったら、擬似ヒルベルト曲線のパスに従って、新しい同じサイズのキャンバス上でピクセルを再配置します。以下のために2**nサイズの正方形の画像あなたは、擬似ヒルベルト曲線のn番目の反復を使用する必要があります。各ピクセルは、新しいキャンバス上のちょうど1つの場所に配置されます。元々左上のポイント(スネークカーブの開始点)がそのまま残り、右下のポイント(スネークカーブの終了点)が右上に配置されるように、イメージを展開する必要があります。

I / O

プログラムまたは関数は、標準的な方法で指定された制約の画像を取り込み、標準的な方法で別の画像を出力する必要があります。

得点

これは、勝ちが最も少ないプログラムです。

入力

モンドリアン

出力

出力1


入力

ロスコ

出力

出力2


入力

スクランブル

出力

ライオン


また、空白の白または単色のイメージでテストして、ピクセルが欠落していないことを確認することをお勧めします。

あなたの答えにあなた自身の結果を含めてください。


入力として画像の代わりにRGB値の配列を使用しても大丈夫ですか?出力はどうですか?
ジョンファンミン

@JHMいいえ、できません。ただし、任意の画像形式を選択できます。言語に組み込みの画像サポートがない場合は、RGB値の配列に非常に類似した非圧縮の.ppmファイルを使用できます。
小麦ウィザード

回答:


8

Mathematica、286273バイト

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}]

head を使用してlby 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

結果StringListの文字に変換します。

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

次の名前のない関数:

  • 2番目の入力がの場合、"-"最初の入力の2番目の要素にを掛けますI
  • 2番目の入力がの場合、"+"最初の入力の2番目の要素をで除算しIます。
  • 2番目の入力がの場合、"F"最初の入力を2番目の入力のReIm(入力の実部と虚部を分離する)だけ増やします。
FoldList [...、{{1,1}、I}、...]

から始めて{{1,1},I}List文字の各要素を2番目の入力として使用して、上記の名前のない関数を累積的に適用します。このコードは、すべての反復の出力を生成します。

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

それぞれの2番目の要素を取り除き、List重複を削除します。(この時点までのステップListは、ヒルベルト曲線の座標を生成します)

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

入力RGB配列を解きます(1行おきに反転し、平坦化します)。

Thread[ ... -> ... ]

Rule最初の入力の最初の要素(ヒルベルト曲線の座標)が2番目の入力の最初の要素(展開された画像)、2番目の要素が2番目の入力などとペアになるようにオブジェクトを作成します。

... ~ReplacePart~ ...

これらの代替適用RuleにSをArray第二のステップから。

Image

RGB値の配列に変換しますImage

サンプルイン/アウト

入力:

テストケース1

出力:

出力


入力:

鋼の錬金術師のエドワードとアルフォンス・エルリック

出力:

ワット

逆関数(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

Reravelingが適用されました:
-Sは各チャネル
に対して繰り返されます-Octaveデータは列ごとに配置されているため、順列が適用されました

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

サンプル画像:

ここに画像の説明を入力してください

ここに画像の説明を入力してください

ここに画像の説明を入力してください

ここに画像の説明を入力してください


I / Oの使用を避けたい場合は、プログラムを関数として機能させることを選択できます。
小麦ウィザード

function + endキーワードはより多くのバイトを消費します!
rahnema1 16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.