wavelet noise and modified noise 2

by syoyo


http://lucille.atso-net.jp/blog/archives/2005/08/wavelet_noise_a.html

からの続きで、ここで実際に Perlin noise と wavelet noise を FFT 変換してみようと思う。

FFT 変換は、octave や mathematica などの数値計算ソフトでサポートされているが、
ここでは自分で作成したノイズプログラムを FFT への入力としたいから、
C 言語のライブラリであるほうが都合がよい。

今回は FFT 変換を行うライブラリとして有名な fftw を利用した。
(ちなみに octave では内部で fftw が使われている)

http://www.fftw.org/

クロスプラットフォームであるのも魅力で、cygwin のパッケージなどにも含まれている。
最新版はバージョン 3 で、バージョン 2 からは API 周りなども違っているので注意が必要である。
ここではバージョン 3 を用いた。

フーリエ像の生成は、

フーリエ変換したい元の 2D 画像を作成 -> 離散フーリエ変換(FFT)

という手順で FFT を行うことで得られる。

もちろん入力を離散画像とすることにより、
ナイキスト限界である 2 ピクセル周期以下の高周波は正確に表現できなくなるので、
入力の関数は 2 ピクセル周期以上としなければならない。

つまり、画像の解像度を 256 としたばあい、

for (i = 0; i < 256; i++) {
        image[i] = noise(0.5 * (i + 0.5));
}

と、noise() への引数入力は 1/2 倍以下にする必要がある。
(ほんとはちょうど 1/2 がナイキスト限界になるので、
これよりすこし周期を大きくする必要があると思う)

もちろん、 Perlin ノイズは周期 1 でかつ整数点ではゼロの値となるので、
いずれにせよピクセルサイズに対して 1/2 倍にする必要がある。

Wavelet noise では、今回は、ちょうど 2D 画像と同じ大きさのノイズテーブルを作成している。
論文の中では、ノイズのテーブルを埋める初期の乱数列には、ガウスノイズ gaussianNoise() を
使うことが推奨されており、これは、[-1, 1] の正規分布に従う乱数列となっている。

この正規分布乱数列の生成には、たとえば論文で述べられているように、
Box-Muller 法を用いて求めることができる。

http://en.wikipedia.org/wiki/Box-Muller_transform

しかし、正規分布は無限のサポート [-∞, ∞] を持つため、生成される値は
必ずしも [-1, 1] の範囲にはない。そのため結果を [-1, 1] へ
クランプしなければならない。

これはどうしたらよいかと迷ったが、平均 0, 分散 1 の
正規分布 N(0, 1) の性質から、4 で割ることにした。
( N(0, 1) の場合、x 軸の値は [-4, 4] の間に 100% の確率で分布するため。
正確には +- 3.9 付近らしい)
本当はここらへんはもう少し考慮する必要があるかもしれない。
( [-1, 1] に分布するような分散 a を持つ N(0, a) にしなければ正しくないなど)

fftw によるフーリエ変換

FFTWを使ったサンプルスクリプト
http://kuma2.isl.titech.ac.jp/~tomoya/blog/archives/000008.html

を参考にし、fftwを利用して Perlin noise と wavelet noise のフーリエ変換を
行うコードを angelina に記述した。

http://lucille.atso-net.jp/svn/angelina/noise/

FFTW が出力するフーリエ像では象限の定義が異なるのか、
中心に低周波(DC component)がこない配置となっているようである。
そのため、中心に低周波が来るように、
フーリエ像を画像ファイルに出力する段階で象限の並べ替えを行っている。

以下が結果画像である。


2D Perlin ノイズの画像とそのフーリエ像


2D Wavelet ノイズの画像とそのフーリエ像

どうも Perlin ノイズと Wavelet ノイズでは基本となる周期が異なるようで、
フーリエ像も同スケールの周波数帯となってはいないが、
(wavelet noise のほうがなめらかっぽいのでフーリエ像における周波数帯も低周波部分に寄っている)
とりあえず論文のようなフーリエ像が得られていることがわかるのでよしとする。

wavelet noise のフーリエ像にはかすかに縦線と横線が見える(輝度スケールを大きくすると分かる)が、
これは画像生成時点か画像の境界に、非連続部分の周波数が現れているのかもしれない。

また、Perlin noise のフーリエ像にも、その形からして周期 1 以下(画面外側)の周波数がすこしカットされているので、

ノイズ画像を作るときに、もうすこししっかりとスケールを設定し、またノイズを数値積分計算して
ナイキスト周波数以下の周波数となるようにより正確なピクセル値を決定する必要がありそうだが、
いまのところこれ以上詳細に踏み込む必要もないのでここでやめにする。

次回は multi-band 化の実装と考察の予定である(Olano’s modified noise
も取り上げねばならない)

To be continued…

Advertisements