コンピューター生成のテクスチャ壁ペイント


48

私の部屋の壁の絵の具は、ランダムで、ほとんどフラクタルのような、3次元のテクスチャーです。

画像A

このチャレンジでは、私の壁の一部になりそうなランダム画像を生成するプログラムを作成します。

以下では、壁のさまざまなスポットの画像を10個収集しました。すべての照明はほぼ同じで、カメラは壁から1フィート離れた場所で撮影されました。境界線を均​​等にトリミングして2048 x 2048ピクセルにし、512 x 512にスケーリングしました。上の画像は画像Aです。

これらはサムネイルのみです。画像をクリックするとフルサイズで表示されます。

A: B:C:D:E:画像A 画像B 画像C 画像D 画像E

F: G:H:I:J:画像F 画像G 画像H 画像I 画像J

あなたの仕事は、1〜2 16の正の整数をランダムシードとして取り込むプログラムを作成し、各値に対して、壁の「11番目の画像」であるかのように見える個別の画像を生成することです。私の10枚の画像とあなたの数枚の画像を見ている人が、どちらがコンピュータで生成されたのかわからない場合、あなたは非常にうまくやった!

視聴者がコードを実行せずにそれらを見ることができるように、生成された画像のいくつかを披露してください。

私の画像の照明は、強度や色が完全に均一ではないことがわかります。申し訳ありませんが、より良い照明器具なしでできる最高の方法です。画像に可変照明を使用する必要はありません(可能ですが)。テクスチャは、焦点を当てるより重要なものです。

詳細

  • 画像処理ツールとライブラリを使用できます。
  • 任意の一般的な方法(コマンドライン、標準入力、明らかな変数など)で入力を取得します。
  • 出力画像は、一般的なロスレス画像ファイル形式にすることも、ウィンドウ/クッパに表示することもできます。
  • 私の10個の画像をプログラムで分析できますが、コードを実行している全員がそれらの画像にアクセスできると想定しないでください。
  • プログラムでイメージを生成する必要があります。私の画像の1つまたは他のストック画像のわずかな変形をハードコードすることはできません。(とにかく人々はこれに賛成票を投じるでしょう。)
  • 組み込みの疑似乱数ジェネレーターを使用して、期間が2 16以上であると想定できます。

得点

これは人気コンテストなので、最も投票数の多い回答が勝ちます。


PerlinNoise +切り捨て+シェーディング
タコ

21
私は壁の画像を作ることができないので、代わりに漫画を持っています!
Sp3000

8
@ Sp3000それは多かれ少なかれそれが起こった方法です。私が探していた場合、私はおそらく選んだと思いますけれども、私の天井にも仕事ができる、...
カルバンの趣味

回答:


65

GLSL(+ JavaScript + WebGL)

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

ライブデモ | GitHubリポジトリ

使い方

新しいランダム画像のページをリロードします。特定のシードをフィードする場合は、ブラウザのコンソールを開いてを呼び出しますdrawScreen(seed)。コンソールには、ロード時に使用されるシードが表示されます。

私はこれを多くのプラットフォームで実際にテストしていないので、うまくいかない場合はお知らせください。もちろん、ブラウザはWebGLをサポートする必要があります。エラーは、左側の列またはブラウザのコンソールに表示されます(エラーの種類に応じて)。

New:「可動光源」チェックボックスにチェックを入れることで、壁を少し活気付けることができるようになりました。

この魔術とは何ですか?

GitHubアカウントの周りにこのWebGL定型コードが浮かんでいます。これを使用して、WebGLで2Dグラフィックをすばやくプロトタイプ化します。シェーダーマジックを使用すると、わずかに3Dに見えるようにすることもできます。そのため、素敵なエフェクトを作成する最も早い方法だと思いました。セットアップの大部分はその定型コードからのものであり、この投稿用のライブラリを検討しており、この投稿には含めません。興味がある場合は、GitHub のmain.js(およびそのフォルダー内の他のファイル)をご覧ください。

JavaScriptは、WebGLコンテキストを設定し、シードをシェーダーのユニフォームに保存し、コンテキスト全体に単一のクワッドをレンダリングするだけです。頂点シェーダーは単純なパススルーシェーダーであるため、すべての魔法はフラグメントシェーダーで発生します。それが私がこれをGLSL提出と呼んだ理由です。

コードの最大の部分は、実際にはGitHubで見つけたシンプレックスノイズを生成することです。そのため、以下のコードリストでも同様に省略しています。重要な部分は、snoise(vec2 coords)テクスチャまたは配列ルックアップを使用せずにシンプレックスノイズを返す関数を定義することです。まったくシードされていないため、異なるノイズを取得するためのトリックは、ルックアップを行う場所を決定する際にシードを使用することです。

だからここに行きます:

#ifdef GL_ES
precision mediump float;
#endif
#extension GL_OES_standard_derivatives : enable

uniform float uSeed;
uniform vec2 uLightPos;

varying vec4 vColor;
varying vec4 vPos;

/* ... functions to define snoise(vec2 v) ... */

float tanh(float x)
{
    return (exp(x)-exp(-x))/(exp(x)+exp(-x));
}

void main() {
    float seed = uSeed * 1.61803398875;
    // Light position based on seed passed in from JavaScript.
    vec3 light = vec3(uLightPos, 2.5);
    float x = vPos.x;
    float y = vPos.y;

    // Add a handful of octaves of simplex noise
    float noise = 0.0;
    for ( int i=4; i>0; i-- )
    {
        float oct = pow(2.0,float(i));
        noise += snoise(vec2(mod(seed,13.0)+x*oct,mod(seed*seed,11.0)+y*oct))/oct*4.0;
    }
    // Level off the noise with tanh
    noise = tanh(noise*noise)*2.0;
    // Add two smaller octaves to the top for extra graininess
    noise += sqrt(abs(noise))*snoise(vec2(mod(seed,13.0)+x*32.0,mod(seed*seed,11.0)+y*32.0))/32.0*3.0;
    noise += sqrt(abs(noise))*snoise(vec2(mod(seed,13.0)+x*64.0,mod(seed*seed,11.0)+y*64.0))/64.0*3.0;

    // And now, the lighting
    float dhdx = dFdx(noise);
    float dhdy = dFdy(noise);
    vec3 N = normalize(vec3(-dhdx, -dhdy, 1.0)); // surface normal
    vec3 L = normalize(light - vec3(vPos.x, vPos.y, 0.0)); // direction towards light source
    vec3 V = vec3(0.0, 0.0, 1.0); // direction towards viewpoint (straight up)
    float Rs = dot(2.0*N*dot(N,L) - L, V); // reflection coefficient of specular light, this is actually the dot product of V and and the direction of reflected light
    float k = 1.0; // specular exponent

    vec4 specularColor = vec4(0.4*pow(Rs,k));
    vec4 diffuseColor = vec4(0.508/4.0, 0.457/4.0, 0.417/4.0, 1.0)*dot(N,L);
    vec4 ambientColor = vec4(0.414/3.0, 0.379/3.0, 0.344/3.0, 1.0);

    gl_FragColor = specularColor + diffuseColor + ambientColor;
    gl_FragColor.a = 1.0;
}

それでおしまい。明日はもう少し説明を追加するかもしれませんが、基本的な考え方は次のとおりです。

  • ランダムな光の位置を選択します。
  • 数オクターブのノイズを加算して、フラクタルパターンを生成します。
  • ノイズを二乗して、底を粗く保ちます。
  • ノイズをフィードスルーtanhして、上部を水平にします。
  • 最上層のテクスチャーをもう2オクターブ増やします。
  • 結果の表面の法線を計算します。
  • 鏡面反射光と拡散反射光を使用して、そのサーフェス上で単純なフォンシェーディングを実行します。色は、最初のサンプル画像から選んだいくつかのランダムな色に基づいて選択されます。

17
これは、壁自体よりも現実的です:o-
クエンティン

1
さらにいくつかの「静脈」/「蛇」/「虫」は、この写真を「壁」により適したものにします。しかし、まだいい。
ノヴァ

33

Mathematica Spackling

以下のアプリは、ランダム画像にスペックルを適用します。「新しいパッチ」をクリックすると、使用する新しいランダム画像が生成され、現在の設定に従ってエフェクトが適用されます。効果は、油絵、ガウスフィルター、ポスタリゼーション、およびエンボス加工です。各エフェクトは個別に調整できます。乱数ジェネレータのシードは、1〜2 ^ 16の任意の整数です。

更新:エッジをソフトにするガウスフィルターが、最後に適用される画像効果になりました。この変更により、ポスタリゼーション効果は不要になり、削除されました。

Manipulate[
 GaussianFilter[ImageEffect[ImageEffect[r, {"OilPainting", o}], {"Embossing", e, 1.8}], g],
 Button["new patch", (SeedRandom[seed] r = RandomImage[1, {400, 400}])], 
 {{o, 15, "oil painting"}, 1, 20, 1, ContinuousAction -> False, Appearance -> "Labeled"}, 
 {{e, 1.64, "embossing"}, 0, 5, ContinuousAction -> False, Appearance -> "Labeled"},
 {{g, 5, "Gaussian filter"}, 1, 12, 1, ContinuousAction -> False, Appearance -> "Labeled"},
 {{seed, 1}, 1, 2^16, 1, ContinuousAction -> False, Appearance -> "Labeled"}, 
 Initialization :> (SeedRandom[seed]; r = RandomImage[1, {400, 400}])]

最終結果


説明

説明は、ポスタリゼーションが採用GaussianFilterされ、早期に適用されたわずかに異なるバージョンに基づいています。ただし、各画像効果が画像をどのように変更するかを明確にするのに役立ちます。最終結果は、よりシャープなエッジを持つペイントテクスチャです。ガウスフィルターが最後にのみ適用されると、上の図に示すように、結果はより滑らかになります。

いくつかの画像効果を一度に1つずつ見てみましょう。

開始イメージを生成します。

 r = RandomImage[1, {200, 200}]

ランダム画像


Lenaは、各イメージエフェクトがリアルな画像をどのように変換するかを示します。

Lena = ExampleData[{"TestImage", "Lena"}]

レナ


レナに適用される油絵効果。

ImageEffect[Lena, {"OilPainting", 8}]

レナオイル

ランダム画像に適用された油絵効果。効果が強まりました(8ではなく16)。

 r1 = ImageEffect[r, {"OilPainting", 16}]

油


レナに適用されるガウスフィルター効果(レナの油絵効果バージョンではありません)。半径は10ピクセルです。(最終版では、このエントリの上部に、GaussianFilterが最終効果として適用されます。)

 GaussianFilter[Lena, 10]

レナ・ガウス。


r1に適用されるやや穏やかなガウスフィルター効果。半径は5ピクセルです。

 r2 = GaussianFilter[r1, 5]

ガウス


レナに適用される強力なポスタリゼーション効果。(アプリの最終バージョンでは、ポスタリゼーションを削除しました。しかし、分析の例はポスタリゼーションのある以前のバージョンに基づいていたため、分析には残しておきます。)

 ImageEffect[Lena, {"Posterization", 2}]

レナポスタライズ


r2に適用されたポスタリゼーション効果。

r3 = ImageEffect[r2, {"Posterization", 4}]

ポスタライズ


エンボスレナ

 ImageEffect[Lena, {"Embossing", 1.2, 1.8}]

レナエンボス


エンボスr3は画像処理を完了します。これは、OPの天井のように見えることを意図しています。

 ceilingSample = ImageEffect[r3, {"Embossing", 1.2, 1.8}]

エンボス


好奇心が強い人のために、同じ画像効果を適用したLenaを紹介します。

レナ4


... Lenaイメージを取得する組み込み機能はありますか?笑。
user253751

7
はい。Mathematicaには画像処理テストに使用される約30枚の組み込み画像があります。
DavidC

わずかな変更を加えるとRandomInteger、シードをフィードして特定の出力を保証できます。それとも、エフェクトが適用される開始時の非ランダム画像のような他の何かを意味しますか?
DavidC

1
1から2 ^ 16のシードを受け入れるようになりました。
DavidC

1
+1 Lena will show us how each image effect transforms a life-like pictureが私をLOLにしたからです。奇妙なことに、最終的なレナの画像は、アステカ族またはインカ族が左向きで、頭飾りを身に着けて小枝を銃のように振り回しているように見えます。
レベルリバーセント

13

POV-Ray

多くのゴルフの可能性、走る povray /RENDER wall.pov -h512 -w512 -K234543 ここに画像の説明を入力してください

最初にランダムテクスチャを作成しますが、そこで停止する代わりに、テクスチャを3D高さフィールドに変換して、カメラからの放射状の影をよりリアルにフラッシュします。そして、適切な測定のために、小さなバンプの上部に別のテクスチャを追加します。
ランダムシードをハードコーディングする以外の唯一の方法は、clockアニメーション用の変数を使用することです。これは-K{number}フラグで渡されます

#default{ finish{ ambient 0.1 diffuse 0.9 }} 

camera {location y look_at 0 right x}
light_source {5*y color 1}

#declare R1 = seed (clock); // <= change this

#declare HF_Function  =
 function{
   pigment{
     crackle turbulence 0.6
     color_map{
       [0.00, color 0.01]
       [0.10, color 0.05]
       [0.30, color 0.20]
       [0.50, color 0.31]
       [0.70, color 0.28]
       [1.00, color 0.26]
     }// end color_map
    scale <0.25,0.005,0.25>*0.7 
    translate <500*rand(R1),0,500*rand(R1)>
   } // end pigment
 } // end function

height_field{
  function  512, 512
  { HF_Function(x,0,y).gray * .04 }
  smooth 
  texture { pigment{ color rgb<0.6,0.55,0.5>}
            normal { bumps 0.1 scale 0.005}
            finish { phong .1 phong_size 400}
          } // end of texture  
  translate< -0.5,0.0,-0.5>
}

これを全くゴルフする必要はありません。いい結果だ!:)
マーティンエンダー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.